如何在Java中抽象不同的返回类型?

时间:2014-05-09 13:16:54

标签: java design-patterns

我想这是一种设计模式问题。

我想将几个操作(输入+处理逻辑+输出)建模为实现某些IOperation接口的类。

每个操作可能有不同的输入参数和不同的输出参数。

我可以使用每个操作的构造函数为每个操作指定不同的输入。

但我想以正交方式为每个类获取不同的输出,而不必将接口强制转换为具体类。

明显的方法是[1]转换为具体类并调用返回所需结果的特定方法或[2]将结果包装到某些OperationResult对象中,这反过来也需要向下转换或某些元数据信息+提取器代码。

我想避免处理反射或向下或元数据解释。

Java中是否存在针对此类情况的已知设计?对此有什么好处?

更新 - @Laf,这里有一些具体的例子。我想提取“c”

interface IOperation{
    void execute();
}

public class AddOp implements IOperation{

    private int a;
    private int b;
    private int c;

    public AddOp(int a, int b){
        this.a = a;
        this.b = b;
    }

    @Override
    public void execute() {
        this.c = this.a + this.b;
    }

}

public class AndOp implements IOperation{

    private boolean a;
    private boolean b;
    private boolean c;

    public AndOp(boolean a, boolean b){
        this.a = a;
        this.b = b;
    }

    @Override
    public void execute() {
        this.c = this.a && this.b;
    }

}

3 个答案:

答案 0 :(得分:4)

您似乎可以使用double dispatching

不返回值(即Object),而是返回void并将参数作为参数传递给您希望将结果放入的目标对象。

interface ResultProcessor {
    processTypeA(A item);
    processTypeB(B item);
    processTypeC(C item);
}

interface InputProcessor {
    processInput(ResultProcessor target);
}

class ConcreteInputProcessorA {
    processInput(ResultProcessor target) {
      A result = ...; // Do something
      target.processTypeA(result);
    }
}

class ConcreteInputProcessorB {
    processInput(ResultProcessor target) {
      B result = ...; // Do something
      target.processTypeB(result);
    }
}

class ConcreteInputProcessorC {
    processInput(ResultProcessor target) {
      C result = ...; // Do something
      target.processTypeC(result);
    }
}

更新:例如,使用新编辑的代码,您可以写下:

public class AddOp implements IOperation{

    private int a;
    private int b;
    private int c;

    public AddOp(int a, int b){
        this.a = a;
        this.b = b;
    }

    @Override
    public void execute(Executor ex) {
        this.c = this.a + this.b;
        ex.executeAddOp(this);
    }
}

public class Executor {
    public void executeAddOp(AddOp op) {
        System.out.println("Executing an AndOp... " + op);
    }
}

答案 1 :(得分:1)

可能的方法是这样的:

private <T extends SomeCommonAncestor> T someMethod(InputParamObject i,
        Class<T> respClass)  {...}

您仍然需要返回对象的一些通用接口/抽象类,并且您需要将实现/子类指定为方法参数的一部分。

希望这有帮助。

[编辑]

public interface IOperation{

       public <T extends ResultObject> T execute(Class<T> respClass);
}

public class AndOp implements IOperation{

    private boolean a;
    private boolean b;
    private boolean c;

    public AndOp(boolean a, boolean b){
        this.a = a;
        this.b = b;
    }    


   @Override
   public <T extends ResultObject> T execute(Class<T> respClass)
   {
       BoolWrap ret = new BoolWrap (a & b);
       return ret;
   }

}

class BoolWrap extends ResultObject {
 ...
}

class AndOpTest {
    public void testIt ()
    {
         AndOp op = new AndOp (false, true);
         BoolWrap result = op.execute (BoolWrap.class);
         //Profit?
    }
}

答案 2 :(得分:1)

在考虑了这里发布的一些提案之后,我自己又采用了另一种有趣的方法。

我不会接受它作为最终答案,因为我不认为那些花时间试图帮助的人是公平的。但无论如何我想分享它。

public class SO {

    public static void main(String[] args){
        new SO().new Example().exec();
    }

    interface IResponse{
        //just a tagging interface
    }

    public class IntegerResponse implements IResponse{
        private int i;

        private IntegerResponse(int i) {
            this.i = i;
        }

        protected int getI() {
            return i;
        }

    }

    public class BooleanResponse implements IResponse{
        private boolean b;

        private BooleanResponse(boolean b) {
            this.b = b;
        }

        protected boolean isB() {
            return b;
        }

    }

    interface IOperation<X extends IResponse>{
        void execute();
        <X extends IResponse> X someMethod();
    }



    public class AddOp implements IOperation<IntegerResponse>{

        private int a;
        private int b;
        private int c;

        public AddOp(int a, int b){
            this.a = a;
            this.b = b;
        }

        @Override
        public void execute() {
            this.c = this.a + this.b;
        }

        @SuppressWarnings("unchecked")
        @Override
        public IntegerResponse someMethod() {
            return new IntegerResponse(this.c);
        }

    }

    public class AndOp implements IOperation<BooleanResponse>{

        private boolean a;
        private boolean b;
        private boolean c;

        public AndOp(boolean a, boolean b){
            this.a = a;
            this.b = b;
        }

        @Override
        public void execute() {
            this.c = this.a && this.b;
        }

        @SuppressWarnings("unchecked")
        @Override
        public BooleanResponse someMethod() {
            return new BooleanResponse(this.c);
        }

    }

    public class Example{
        public void exec(){
            IOperation<?> op = new AndOp(true,false);
            BooleanResponse resp = op.someMethod();
            System.out.println(resp.isB());
        }
    }
}