Java设计,如何避免将对象传递给层次结构?!?不可能?

时间:2012-07-12 20:20:05

标签: java oop generics

我有很多课程,请允许我介绍它们,然后在最后提出我的问题:

我有一个容器类,它包含一个复合关系中的两个对象:

public class Container{

    A a;
    B b;

    public someMethod(){
        a.getC().myMethod(b);
    }
}

A和B是超类(或接口),子类型也可以是复合关系中保存的类型。

A包含(接口)类型C的成员:

public class A{
   C c;
}


public interface C{
    public void myMethod(B b);
}

public class D implements C{
    public void myMethod(B b){
        //This code will modify the state of object b, in class Container.
        b.changeState();
    }
}

public class E implements C{
    public void myMethod(B b){
        //This code will modify the state of object b, in class Container.
        b.changeState();
    }
}

我的问题是我希望从容器类中开始的方法修改对象b的状态,该方法最终将层次结构中的代码调用到类D和E-通过动态绑定调用myMethod()。我想这样做,因为我将使用多态来运行正确的myMethod()(取决于对象的类型是D还是E),我希望这样做,而不是写IF语句。

所以我的问题是,将对象b的实例继续传递给类层次结构到myMethod似乎非常糟糕,这样我就可以运行特定于b的代码来修改b的状态。还有什么我可以做的从d和e修改b(统称为c)?

我可以使用接口但不使用泛型来实现这一点 - 但是当我添加泛型时,我遇到类型问题,这让我开始思考我的整个设计是否有缺陷?

编辑:我可以通过使用IF语句轻松地做到这一点 - 但我想要一个使用D类和E类多态的优雅解决方案。

2 个答案:

答案 0 :(得分:2)

首先,如果我正确理解了您的问题,则代码中没有B的实例被“传递”。动态调度只会导致myMethod()的实际类型中的a实现以B的实例作为参数调用。

虽然每次实施myMethod()时必须明确写出参数可能会很乏味,但它没有任何问题。

另一种方法是为A的每个子类/实现赋予B类型的属性。但是,在这种情况下,您必须将构造函数链中的B实例传递给实际具有B属性的类。

您的代码将变为:

public class A{
  C c;

  public A(C c) {
    this.c = c;
}


public interface C{
    public void myMethod(B b);
}

public abstract class CC {
  protected B b;

public CC(B b) {
  this.b = b;

public class D extends CC implements C {
    public D(B b) {
      super(b);
    }
    public void myMethod(){
        b.changeState();
    }
}

public class E extends CC implements C {
    public E(B b) {
      super(b);
    }
    public void myMethod(){
        b.changeState();
    }
}

然后在某处,例如在Container的构造函数中:

b = new B();
a = new A(new E(b));

答案 1 :(得分:0)

您可以将B的实例传递给E的构造函数(或使用setter)。这本身就存在问题,但至少它避免了每次调用myMethod()时都必须传递B,现在不需要参数。

e.g。

B内的某处

E myE = new E(this);

和,在E

final B myB;
public E(B myHigherLevelThing) {
  this.myB = myHigherLevelThing;
}

public void myMethod() {
  myB.changeState();
}

使用最常用的声明界面,我对你的完整层次结构有点困惑,所以那里可能还有改进空间......