设计建议:改变班级行为

时间:2015-06-22 15:23:14

标签: java object-oriented-analysis

下面我试图用一个例子来解释这个问题。

我们有一个Caller.java

Caller.java:调用一系列Actors按顺序执行某些步骤。

Actor.java:包含action()方法的抽象类

ActorOne.java:实现action()方法

ActorTwo.java:实现action()方法

ActorThree.java:实现action()方法

在运行时,根据要完成的任务,在Caller.java中准备一组类,并使用Reflection进行实例化。

Actor.java: callActions(){
Class[] classes = [ActorOne.class, ActorTwo.class]

for(Class clazz : classes){
   Actor actor = (Actor) clazz.newInstance();
   actor.action(); 
}
}

在某些情况下,我知道callActions.java中的运行时,我需要通知ActorTwo以不同方式执行action方法。

我的解决方案是使用Reflection API将该标志传递给ActorTwo对象,并在action()方法内放置if / else以执行标记特定操作。

有没有更好的方法来设计解决方案,以便我可以避免在ActorTwo.action()方法中使用if / else?

最好的问候

3 个答案:

答案 0 :(得分:1)

您的界面上可以有两种方法。 ActorOne和ActorThree会将一个方法的实现委托给另一个方法(也许抽象的超级类会这样做)。演员两个会做些不同的事情。

你可以拥有另一个使用不同方法的接口,让ActorTwo实现它,并在运行时检查你的对象是否支持它

 if(inSpecialCase && actor instanceof Actor2) {
   ((Actor2)actor).specialMethod()

Eclipse的工作方式与第二个建议相似,以保持可扩展性和兼容性(新接口随着时间的推移而创建,行为会根据代码支持的级别进行调整)。

答案 1 :(得分:1)

另一种选择是使action()方法采用一组参数(如main(...)一样)。这样,ActorTwo可以检查参数以查看它是否在特殊情况下,而其他Actors可以忽略输入。

public abstract class Actor{
    public abstract void action(String[] args);
}

public class Actor2 extends Actor{

    public void action(String[] args){
        if(args != null && args.length > 0 && args[0].equals("SPECIAL_CASE"){
            //Do special case things
        } else {
            //Do regular case things
        }
    }
}

这种形式为您提供了最大的灵活性,可以为任何演员添加额外的案例。

答案 2 :(得分:1)

使用多态。在ActorTwo.java中定义另一个名为action(flag)的方法,然后在此方法中实现新行为。如果您不想传递标志,则应调用正常的action()。如果要在运行时传递标志,则应调用action(flag)。

建议,尽可能避免反思。它减慢了执行速度。如果您的代码无法避免反射,那就没问题了。