问题
I am trying to find a way to bypass the use of instanceof. I've created a class Item which has multiple subclasses like WeaponItem and BodyItem. Now I would like to make to do a call such as equip(Item) and it should determine by itself which overloaded function it should call such as equip(BodyItem).
Is there a way to bypass the use of instanceof for this case and what would you recommend? I've heard that in most cases using instanceof is bad practice and therefor I want to know what the alternatives are.
Code:
inv.equip(it); // inv = inventory object, it = Item
An example of equip function within inventory class how I preferably want it
public void equip(HelmItem it)
{
if (it != this.getHelm())
{
this.setHelm(it);
}
}
How I had it before:
public void equip(Item it)
{
if (it instanceof WeaponItem)
{
if (it != this.getWeapon())
{
this.setWeapon((WeaponItem) it);
}
} etc for all subclasses of item
}
回答1:
Indeed, this could be solved with a visitor pattern.
However, it does not have to be a full-blown visitor, but a simplified variation of it. You could pass the inventory to the item and let the item do whatever it wants with it:
abstract class Item {
public abstract void equip(Inventory inv);
}
class HelmItem extends Item {
@Override
public void equip(Inventory inv) {
inv.setHelm(this);
}
}
class WeaponItem extends Item {
@Override
public void equip(Inventory inv) {
inv.setWeapon(this);
}
}
Then you can just call:
it.equip(inv)
without the instanceof
operator.
回答2:
Why not put the method in the Item
concrete class, and it can equip itself? It's a little counter intuitive but it would solve your problem.
public class SomeConcreteItem extends Item {
public void equip(Body body) {
// Just an example.
body.getSections().get(0).equip(this);
}
}
That way, the concrete implementation knows how to equip itself and the classes that use it don't care. You can reference it by the Item
superclass and provided that the Item
superclass has an abstract method public void equip(Body body);
, then you don't ever need to know about the concrete implementation and, therefore, no need for the instanceof
operator.
A Note on Introducing a Design Pattern
You should be careful about introducing Design Patterns. People have a bad habit of leaping straight to a complicated pattern to solve a problem, when really something simpler and (in my opinion) more elegant is available.
来源:https://stackoverflow.com/questions/30953608/avoiding-instanceof-java