重新设计OOP拆分与个人的组合接口

时间:2013-04-22 20:35:48

标签: java oop architecture polymorphism

我试图了解如何以干净且“可设计”的方式避免双重进入以下情况:

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
  • 认为将来我可能会有额外的“ables”

谢谢, 射线。

5 个答案:

答案 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");
        }
}