我试图了解如何以干净且“可设计”的方式避免双重进入以下情况:
public interface ICommandAble
{ }
public interface ILogAble extends ICommandAble
{ }
public interface IMonitorAble extends ICommandAble
{ }
public abstract class ClassAbs
{ }
public class A extends ClassAbs implements IMonitorAble, ILogAble
{ }
测试方法:
public void test()
{
A a=new A();
List<ICommandAble>commandList=new ArrayList<ICommandAble>()
if (a instanceof ILogAble)
{
ILogAble logAbleItem=(ILogAble)a;
commandList.add(logAbleItem);
}
if (a instanceof IMonitorAble) {
IMonitorAble monitorAbleItem=(IMonitorAble)a;
commandList.add(monitorAbleItem);
}
for(ICommandAble item: commandList)
{
if(item instanceof IMonitorAble)
{
log.debug("is monitorable");
}
if(item instanceof ILogAble)
{
log.debug("is logable");
}
}
输出是:
2013-04-22 18:25:00,498 com ... [DEBUG]是可以监视的
2013-04-22 18:25:02,150 com .... [DEBUG]可以登录
2013-04-22 18:25:08,322 com .... [DEBUG]是可以监视的
2013-04-22 18:25:08,977 com .... [DEBUG]可以登录
这会导致我的程序为每个“xAble”执行双重执行
我希望看到:
2013-04-22 18:25:00,498 com ... [DEBUG]是可以监视的
2013-04-22 18:25:02,150 com .... [DEBUG]可以登录
我应该如何重新设计(以一种干净的方式)第二个迭代器条件将基于引用类型而不是实例类型。得到这样的东西:
2013-04-22 18:25:00,498 com... [DEBUG] is monitorable
2013-04-22 18:25:02,150 com.... [DEBUG] is logable
谢谢, 射线。
答案 0 :(得分:0)
由于您只是向List
添加项目,因此您可以更改代码以验证它是否是ICommandAble
的实例,如下所示:
if (a instanceof ICommandAble) {
commandList.add(a);
}
答案 1 :(得分:0)
这是因为你将a
添加到commandList中两次,一次是为了可记录而又是为了监视。
您应该将2个if语句合并为1:
if (a instanceof ILogAble || a instanceof IMonitorAble)
{
commandList.add(a);
}
答案 2 :(得分:0)
如果您正在测试对象以查看它们是否是接口实例,那么它们必须实现该接口。他们也可以始终实现其他接口。在您的场景中,要实现所需的输出,必须使对象只实现两个接口中的一个。
public class Test {
public interface ICommandAble {
}
public interface ILogAble extends ICommandAble {
}
public interface IMonitorAble extends ICommandAble {
}
public abstract class ClassAbs {
}
public class A extends ClassAbs implements IMonitorAble, ILogAble {
}
public class B extends ClassAbs implements IMonitorAble {
}
public class C extends ClassAbs implements ILogAble {
}
public void test() {
A a = new A();
B b = new B();
C c = new C();
List<ICommandAble> commandList = new ArrayList<ICommandAble>();
commandList.add(a); // Remove this line to just get the two printouts.
commandList.add(b);
commandList.add(c);
for (ICommandAble item : commandList) {
if (item instanceof IMonitorAble) {
System.out.println(item.getClass().getSimpleName() + " is monitorable");
}
if (item instanceof ILogAble) {
System.out.println(item.getClass().getSimpleName() + " is logable");
}
}
}
public static void main(String args[]) {
new Test().test();
}
}
打印
A is monitorable
A is logable
B is monitorable
C is logable
我在列表中添加了A
以证明其不同之处。
答案 3 :(得分:0)
将实例添加到散列集而不是列表中,这样即使实例添加多次,实例也会出现一次
答案 4 :(得分:0)
正如其他答案已经解释过的那样,你想要的东西是不可能的。您需要使用多个列表。您可以在Map中组织此列表以使其更易于维护,但也许您应该重新考虑您的设计。
这是一种如何轻松使用多个列表的方法:
public interface ICommandAble {}
public interface ILogAble extends ICommandAble {}
public interface IMonitorAble extends ICommandAble {}
public abstract class ClassAbs {}
public class A extends ClassAbs implements IMonitorAble, ILogAble {}
public List<ICommandAble> getList(LinkedHashMap<Class<? extends ICommandAble>, List<ICommandAble>> commandList,
Class<? extends ICommandAble> clazz) {
if (commandList.get(clazz) != null)
return commandList.get(clazz);
ArrayList<ICommandAble> l = new ArrayList<>();
commandList.put(clazz, l);
return l;
}
public void test() {
A a = new A();
LinkedHashMap<Class<? extends ICommandAble>, List<ICommandAble>> commandList = new LinkedHashMap<>();
if (a instanceof ILogAble)
getList(commandList, ILogAble.class).add(a);
if (a instanceof IMonitorAble)
getList(commandList, IMonitorAble.class).add(a);
for (Class<? extends ICommandAble> clazz : commandList.keySet())
for (ICommandAble item : commandList.get(clazz)) {
if (clazz.equals(IMonitorAble.class))
log("is monitorable");
if (clazz.equals(ILogAble.class))
log("is logable");
}
}