根据Java中Object的类型选择实现

时间:2016-04-16 19:29:54

标签: java design-patterns genetic-algorithm strategy-pattern visitor-pattern

我有一个父类型

public class IObject{}

并且可以有很多子类(将来甚至是新的子类)

public class Object1 extends IObject{}
public class Object2 extends IObject{}
public class Object3 extends IObject{}
...
public class ObjectN extends IObject{}

然后根据这些对象的类型,我必须做不同的操作。

public class StrategyForObject1(){void do{}}
public class StrategyForObject2(){void do{}}
public class StrategyForObject3(){void do{}}
...
public class StrategyForObjectN(){void do{}}

所以我想从我的Context类:

   public Conext {
    IObject o;

    public void setObject(IObject o) {
        this.o = o;
    }

    void logic() {
        if (o instanceOf Object1) {
            new StrategyForObject1().do();
        }
        if (o instanceOf Object2) {
            new StrategyForObject2().do();
        }
        if (o instanceOf Object3) {
            new StrategyForObject3().do();
        }
        ...
        if (o instanceOf ObjectN) {
            new StrategyForObjectN().do();
        }
    }
}

所以基于执行不同算法的类型,但是我希望像Strategy模式那样可扩展,如果我需要添加新的IObject子类来添加新的StrategyForObject**N**类,但是不要改变Conext类。 在战略模式中,我们必须指定战略,但在这里我们必须做相反的事情:根据对象的类型选择策略。如何以最好的方式在Java中做到这一点?

修改: 无法更改IObject以添加其他方法。 我必须将逻辑与数据分开,因此不希望在Object1类中添加逻辑实现。

4 个答案:

答案 0 :(得分:4)

我认为你需要实现访问者模式。基本上你拥有的东西看起来像这样:

interface IObjectVisitor {
    void visit(IObject1 obj1);
    void visit(IObject2 obj2);
    ...
    void visit(IObjectN objN);
}    
interface IObjectVisitable {
    void accept(IObjectVisitor visitor);
}
public abstract class IObject implements IObjectVisitable {
   ...
}
public class IObject1 extends IObject {
    public void accept(IObjectVisitor visitor) {
        visitor.visit(this);
    }
}
public class IObject2 extends IObject {
    public void accept(IObjectVisitor visitor) {
        visitor.visit(this);
    }
}
...
public class IObjectN extends IObject {
    public void accept(IObjectVisitor visitor) {
        visitor.visit(this);
    }
}
public class SomeLogicIObjectVisitor implements IObjectVisitor {
    void visit(IObject1 obj1) {
        //something with obj1
    }
    void visit(IObject2 obj2) {
        //something with obj2
    }
    ...
    void visit(IObjectN objN) {
        //something with objN
    }
}

然后你有一些逻辑适用于这样的IObject:

public void someLogic(IObject obj) {
    SomeLogicIObjectVisitor visitor = new SomeLogicIObjectVisitor():
    visitor.visit(obj);
}

面向对象,这是您可以实现的最佳模式。原因是它允许您采用模块化和可扩展的方法,应用正确的关注点分离。看看@ nhouser9提供的答案。虽然在IObject中定义abstract void do();似乎乍看之下,但您将在您的域对象中嵌入业务逻辑,这很可能不属于那里。此外,如果现在考虑其他一些逻辑,让我们调用它,“logic2”现在你别无选择,只能在每个IObject实现上创建abstract void do2();,并继续在那里嵌入业务逻辑。使用访问者模式,IObject实现不会改变,并且您没有在IObject中嵌入任何逻辑,只需创建一个新的访问者Logic2IObjectVisitor并在那里实现每个IObject实现的逻辑。你会这样称呼它:

public void someLogic2(IObject obj) {
    Logic2IObjectVisitor visitor = new Logic2IObjectVisitor():
    visitor.visit(obj);
}

答案 1 :(得分:2)

首先,您的IObject类应该是抽象的,因为它只是为了被其他类扩展。然后你可以在其中声明一个必须由继承它的类重写的方法,如下所示:

public abstract class IObject {
    abstract void do();
}

然后,实现它的所有类必须使用自定义逻辑覆盖该方法:

public class Object1 extends IObject {
  @Override
  void do() {
    //custom logic
  }
}

换句话说,您应该将do()放在Object1内而不是StrategyForObject1

此结构允许您对IObject类型的通用对象调用do(),因为IObject的所有子项都将实现do()方法。所以在你的逻辑方法中,你可以这样做:

void logic(){
 o.do();
}

答案 2 :(得分:2)

查看访客模式。我认为这正是你要找的。

编辑:澄清:

import java.util.Arrays;
import java.util.List;

public class Test {
    public static abstract class IObject {
        public abstract void doSomeWork(StrategyVisitor strat);
    }

    public static class Object1 extends IObject {
        @Override
        public void doSomeWork(StrategyVisitor strat) {
            strat.doWork(this);
        }
    }

    public static class Object2 extends IObject {
        @Override
        public void doSomeWork(StrategyVisitor strat) {
            strat.doWork(this);
        }
    }

    public static class Object3 extends IObject {
        @Override
        public void doSomeWork(StrategyVisitor strat) {
            strat.doWork(this);
        }
    }

    public static interface StrategyVisitor {
        void doWork(Object1 o);

        void doWork(Object2 o);

        void doWork(Object3 o);
    }

    public static void main(String[] args) {
        List<IObject> objs = Arrays.asList(new Object1(), new Object2(), new Object3());

        StrategyVisitor visitor = new StrategyVisitor() {
            @Override
            public void doWork(Object1 o) {
                System.out.println("Object1");
            }

            @Override
            public void doWork(Object2 o) {
                System.out.println("Object2");
            }

            @Override
            public void doWork(Object3 o) {
                System.out.println("Object3");
            }
        };

        objs.stream().forEach(o -> o.doSomeWork(visitor));
    }
}

(见https://en.wikipedia.org/wiki/Visitor_pattern

答案 3 :(得分:1)

IObject可以使用抽象方法do()

然后,上下文的logic()方法只调用o.do()

这是多态性的典型例子。