0

我试图了解如何以一种干净且“可设计”的方式避免重复输入以下场景:

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
  • 认为将来我可能会有更多的“能力”

谢谢,雷。

4

5 回答 5

0

由于您只是将项目添加到 中List,因此您可以更改代码以验证它是否是 的实例ICommandAble,如下所示:

if (a instanceof ICommandAble) {
   commandList.add(a);
}
于 2013-04-22T20:44:10.723 回答
0

这是因为您a两次添加到 commandList 中,一次是可记录的,另一次是可监控的。

您应该将 2 个 if 语句合并为 1 个:

if (a instanceof ILogAble || a instanceof IMonitorAble)
{
    commandList.add(a);
}
于 2013-04-22T20:57:51.543 回答
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列表中添加了一个来展示差异。

于 2013-04-22T21:21:10.303 回答
0

将实例添加到哈希集而不是列表中,这样即使添加了多次,实例也会出现一次

于 2013-04-23T02:56:55.253 回答
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");
        }
}
于 2013-04-23T15:21:13.063 回答