I have class structure where
public abstract class AbstractBuilding implements some non-relevant
interfaces for this question.
public abstract class AbstractAnimalBuilding extends AbstractBuiling
public class AnimalBuildingA extends AbstractAnimalBuildingpublic class AnimalBuildingB extends AbstractAnimalBuildingpublic class AnimalBuildingC extends AbstractAnimalBuildingpublic class AnimalBuildingD extends AbstractAnimalBuildingIn a totally separate class I have the following method:
@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);
}
Where animalBuildings is a Set<AbstractAnimalBuilding> containing any combination of AnimalBuildingX's.
Assuming the structure at the top needs to be kept (eg, AnimalBuildingX HAS to extend AbstractAnimalBuilding), what would be a better approach than the multiple if-then-else statements in determining what kind of building animalBuilding is?
Would it feasible to simply create a new Interface as outlined in this question and have each AnimalBuildingX implement it while still extending AbstractAnimalBuilding or is there a way I can do it using the structure I currently have.
This is difficult to answer in general without more context.
One possibility is to create an abstract method in AbstractBuilding and implement it differently in the subclasses.
Another possibility is to use the visitor pattern.
It depends on the action you want to take on behalf of the derived class type. If an action has to be taken which can be perfomed without the need, that the calling class knows the concrete implementation of AnimalBuilding the interface method is appropriate. This usually is the case if you can find a common method description which is implemented differently for each concrete class (e.g. getName()).
If you need to do specific actions dependent on the concrete class (e.g. AnimalBuildingA differs from AnimalBuldingB), you can implement the 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);
...
}
The implementation of the accept-method usually is the one liner
return v.visit(this);
Then you create an implementation of the Abstract visitor which does the work you want to perform in the loop. The loop then looks like this
ConcreteAnimalBuildingVisitor v;
for (AbstractAnimalBuilding animalBuilding: animalBuildings)
animalBuilding.accept(v);
This way, the concrete class "identifies" itself to the concrete visior which then can perform the appropriate action.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With