迭代循环

时间:2015-10-23 06:26:39

标签: java javafx interface polymorphism

我有类结构

  • public abstract class AbstractBuilding 实现了一些不相关的内容 这个问题的接口。
  • public abstract class AbstractAnimalBuilding extends AbstractBuiling
    遵循这种结构的少数类:
  • public class AnimalBuildingA extends AbstractAnimalBuilding
  • public class AnimalBuildingB extends AbstractAnimalBuilding
  • public class AnimalBuildingC extends AbstractAnimalBuilding
  • public class AnimalBuildingD extends AbstractAnimalBuilding

在一个完全独立的课程中,我有以下方法:

@FXML
private Button btnAnimalBuildingA;
@FXML
private Button btnAnimalBuildingB;
@FXML
private Button btnAnimalBuildingC;
@FXML
private Button btnAnimalBuildingD;

for (AbstractAnimalBuilding animalBuilding: animalBuildings){
    if (animalBuilding instanceof AnimalBuildingA) {
        changeButtonDisplay(btnAnimalBuildingA)
    } else if (animalBuilding instanceof AnimalBuildingB){
        changeButtonDisplay(btnAnimalBuildingB)
    } else if (animalBuilding instanceof AnimalBuildingC) {
        changeButtonDisplay(btnAnimalBuildingC)
    } else if (animalBuilding instanceof AnimalBuildingD){
        changeButtonDisplay(btnAnimalBuildingD)
        //Do something specific here
    }
}

private void changeButtonDisplay(Button buttonToChange){
    button.setVisible(true);
}

其中animalBuildings是包含Set<AbstractAnimalBuilding>的任意组合的AnimalBuildingX

假设需要保留顶部的结构(例如,AnimalBuildingX HAS 以扩展AbstractAnimalBuilding),那么什么是比{{1}更好的方法确定if-then-else是什么类型的建筑物的语句?

this问题中所述简单地创建一个新的animalBuilding并且每个Interface AnimalBuildingX同时仍在扩展implement或是否存在我可以使用我目前拥有的结构来做到这一点。

3 个答案:

答案 0 :(得分:4)

如果没有更多背景,这很难回答。

一种可能性是在AbstractBuilding中创建一个抽象方法,并在子类中以不同方式实现它。

另一种可能性是使用visitor pattern

答案 1 :(得分:3)

这取决于您要代表派生类类型采取的操作。如果必须采取可以在不需要的情况下执行的操作,则调用类知道接口方法的AnimalBuilding的具体实现是合适的。如果您能找到针对每个具体类(例如getName())实现不同的通用方法描述,通常就是这种情况。

如果您需要根据具体类别执行特定操作(例如AnimalBuildingAAnimalBuldingB不同),则可以实施visitor pattern

public abstract class AbstractAnimalBuilding {
    ...
    public abstract void accept(AnimalBuildingVisitor v);
}

public interface class AnimalBuildingVisitor<T> {

    public T visit(AnimalBuildingA a);
    public T visit(AnimalBuildingB b);
    ...
}

accept-method的实现通常是一个班轮

return v.visit(this);

然后,您创建一个Abstract访问器的实现,它执行您想要在循环中执行的工作。然后循环看起来像这样

ConcreteAnimalBuildingVisitor v;
for (AbstractAnimalBuilding animalBuilding: animalBuildings)
    animalBuilding.accept(v);

通过这种方式,具体类“识别”自己的具体视角,然后可以执行适当的动作。

答案 2 :(得分:2)

您可以使用泛型保持当前结构并实现您的期望:

首先,我们需要定义一个通用的处理程序接口:

public interface AnimalBuildingHandler<T extends AbstractAnimalBuilding> {
    void handle(T type);
}

然后,在您自己的自定义类中,我们可以为每种类型实现特定的功能:

/* Here you can define all  */
public void handleAnimalBuildingA(AnimalBuildingA animalBuildingA) {
    /**
     * Implement your custom handling here
     */
    System.out.println("Handling AnimalBuildingA" + animalBuildingA);
}

public void handleAnimalBuildingB(AnimalBuildingB animalBuildingB) {
    /**
     * Implement your custom handling here
     */
    System.out.println("Handling AnimalBuildingA" + animalBuildingB);
}

然后,我们可以通过将处理程序映射到类型来创建一个实现上述AnimalBuildingHandler接口的魔术处理程序类:

private Map<Class<? extends AbstractAnimalBuilding>, AnimalBuildingHandler<? extends AbstractAnimalBuilding>> handlersMapping;

{ /* default instance initializer */
    handlersMapping = new HashMap<>();
    handlersMapping.put(AnimalBuildingA.class, new AnimalBuildingHandler<AnimalBuildingA>() {
        @Override
        public void handle(AnimalBuildingA type) {
            handleAnimalBuildingA(type);
        }
    });

    handlersMapping.put(AnimalBuildingB.class, new AnimalBuildingHandler<AnimalBuildingB>() {
        @Override
        public void handle(AnimalBuildingB type) {
            handleAnimalBuildingB(type);
        }
    });
}

@Override
public void handle(AbstractAnimalBuilding type) {
    AnimalBuildingHandler abh = handlersMapping.get(type.getClass());
    abh.handle(type);
}

最后,测试方法:

public <T extends AbstractAnimalBuilding> void test() {

    List<T> allAnimalBuildings = new ArrayList<>();

    allAnimalBuildings.add((T) new AnimalBuildingA());
    allAnimalBuildings.add((T) new AnimalBuildingB());

    for (AbstractAnimalBuilding aab : allAnimalBuildings) {
        handle(aab);
    }
}