Avoiding instanceof Java - java

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
}

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.

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.

Related

What pattern should be used, strategy?

I do have a service which needs to handle two types of meal.
#Service
class MealService {
private final List<MealStrategy> strategies;
MealService(…) {
this.strategies = strategies;
}
void handle() {
var foo = …;
var bar = …;
strategies.forEach(s -> s.remove(foo, bar));
}
}
There are two strategies, ‘BurgerStrategy’ and ‘PastaStrategy’. Both implements Strategy interface with one method called remove which takes two parameters.
BurgerStrategy class retrieves meals of enum type burger from the database and iterate over them and perform some operations. Similar stuff does the PastaStrategy.
The question is, does it make sense to call it Strategy and implement it this way or not?
Also, how to handle duplications of the code in those two services, let’s say both share the same private methods. Does it make sense to create a Helper class or something?
does it make sense to call it Strategy and implement it this way or not
I think these classes ‘BurgerStrategy’ and ‘PastaStrategy’ have common behaviour. Strategy pattern is used when you want to inject one strategy and use it. However, you are iterating through all behaviors. You did not set behaviour by getting one strategy and stick with it. So, in my honour opinion, I think it is better to avoid Strategy word here.
So strategy pattern would look like this. I am sorry, I am not Java guy. Let me show via C#. But I've provided comments of how code could look in Java.
This is our abstraction of strategy:
public interface ISoundBehaviour
{
void Make();
}
and its concrete implementation:
public class DogSound : ISoundBehaviour // implements in Java
{
public void Make()
{
Console.WriteLine("Woof");
}
}
public class CatSound : ISoundBehaviour
{
public void Make()
{
Console.WriteLine("Meow");
}
}
And then we stick with one behaviour that can also be replaced:
public class Dog
{
ISoundBehaviour _soundBehaviour;
public Dog(ISoundBehaviour soundBehaviour)
{
_soundBehaviour = soundBehaviour;
}
public void Bark()
{
_soundBehaviour.Make();
}
public void SetAnotherSound(ISoundBehaviour anotherSoundBehaviour)
{
_soundBehaviour = anotherSoundBehaviour;
}
}
how to handle duplications of the code in those two services, let’s say both share the same private methods.
You can create one base, abstract class. So basic idea is to put common logic into some base common class. Then we should create abstract method in abstract class. Why? By doing this, subclasses will have particular logic for concrete case. Let me show an example.
An abstract class which has common behaviour:
public abstract class BaseMeal
{
// I am not Java guy, but if I am not mistaken, in Java,
// if you do not want method to be overriden, you shoud use `final` keyword
public void CommonBehaviourHere()
{
// put here code that can be shared among subclasses to avoid code duplication
}
public abstract void UnCommonBehaviourShouldBeImplementedBySubclass();
}
And its concrete implementations:
public class BurgerSubclass : BaseMeal // extends in Java
{
public override void UnCommonBehaviourShouldBeImplementedBySubclass()
{
throw new NotImplementedException();
}
}
public class PastaSubclass : BaseMeal // extends in Java
{
public override void UnCommonBehaviourShouldBeImplementedBySubclass()
{
throw new NotImplementedException();
}
}

Refactoring legacy instanceof switch casing via design patterns

My company's legacy code is suffering from prevalent usage of instanceof switch-casing, in the form of:
if(object instanceof TypeA) {
TypeA typeA = (TypeA) object;
...
...
}
else if(object instanceof TypeB) {
TypeB typeB = (TypeB) object;
...
...
}
...
...
To make things worse, several of the TypeX classes in questions are actually wrappers of classes found in 3rd party libraries.
The suggested approach of using the visitor design pattern and dedicated visitor design pattern wrappers on 3rd party classes as seen here (instanceof -> Visitor DP) and here (Visitor DP with 3rd party classes) seems like a good approach.
However, during a code review session where this approach was suggested, the question of the additonal overhead of boilerplate code required by each refactoring of the instaceof switch-casing has lead to this mechanism being declined.
I would like to fix this ongoing issue and I am considering a generic approach to the problem:
A utility class which will wrap the visitor design pattern with generic referencing to the visited objects. The idea is to implement the generic core of the visitor utility class once and only once, and provide specific implementations to the TypeX object behaviour where needed - hopefully even reusing some implementations via OO extention of the functionality implementing classes.
My question is - has anyone here done something similiar? If not - can you point out any pros/cons that might be relevant?
EDIT :
Too much boilerplate code = implementing the visitor design pattern specifically for each instance of an instanceof switch-case. This is obviously redundent and will cause a lot of code duplication, if the visitor DP is not implemented using generics.
As for the generic visitor DP utility I had in mind :
First of all, usage of reflection with the visitor DP as seen here.
Second, the following usage of generics (based on the reflective visitor):
public interface ReflectiveVisitor<GenericReturn,GenericMetaData>
{
public GenericReturn visit(Object o, GenericMetaData meta);
}
public interface ReflectiveVisitable<A,B>
{
public GenericReturn accept(Visitor visitor, GenericMetaData meta);
}
GenericReturn and GenericMetaData are interfaces aimed at providing any additionally required meta data for specific logics to be implemented, and to provide versatility for return types returned by the visitor DP.
Thanks in advance!
EDIT : Boiler plate coding when refactoring from instanceof to the visitor :
A common use case I'd have to handle is instanceof switchcasing in order to perform single API calls of concrete implementations :
public class BoilerPlateExample
...
if(object instanceof TypeA) {
((TypeA) object).specificMethodTypeA(...)......;
}
else if(object instanceof TypeB) {
((TypeB) object).completeyDifferentTypeBMethod(...)......;
}
...
...
As for the visitor design handling this?
public interface Visitor
{
// notice how I just binded my interface to a specific set of methods?
// this interface will have to be generic in order to avoid an influx of
// of dedicated interfaces
public void visit(TypeA typeA);
public void visit(TypeB typeB);
}
public interface Visitable
{
public void accept(Visitor visitor);
}
public class BoilerPlateExampleVisitable<T> implements Visitable
{
// This is basically a wrapper on the Types
private T typeX;
public BoilerPlateExampleVisitable (T typeX) {
this.typeX = typeX;
}
public void accept(Visitor visitor) {
visitor.visit(typeX);
}
}
public class BoilerPlateExampleVisitor implements Visitor
{
public void visit(TypeA typeA) {
typeA.specificMethodTypeA(...)......;
}
public void visit(TypeB typeB) {
typeB.completeyDifferentTypeBMethod(...)......;
}
}
public static final BoilerPlateExampleVisitor BOILER_PLATE_EXAMPLE_VISITOR = new BoilerPlateExampleVisitor();
public static void main(....) {
TypeA object = .....; // created by factory
BoilerPlateExampleVisitable boilerPlateVisitable = VisitableFactory.create(object); // created by dedicated factory, warning due to implicit generics
boilerPlateVisitable.accept(BOILER_PLATE_EXAMPLE_VISITOR);
}
TL;DR: Let's say that you have N classes with M operations each. You need the visitor pattern only if M may grow and N is already big. Else use polymorphism.
Maybe I will push an open door, because you already thought of this, but here are a few thoughts.
Visitor pattern
In the generic case, you will use the visitor pattern only if you want to add new operations without refactoring all classes. That is when M may grow and N is already big.
For every new operation, you create a new visitor. This visitor accepts the N classes and handles the operation for each of them:
public class NewOperationVisitor implements Visitor
{
public void visit(TypeA typeA) {
// apply my new operation to typeA
}
public void visit(TypeB typeB) {
// apply my new operation to typeB
}
...
}
Thus, you don't have to add the new operation to all the N classes, but you have to refactor every visitor if you add a class.
Polymorphism
Now, if M is stable, please avoid the visitor pattern: use polymorphism. Every class has a well defined set of methods (roughly one per operation). If you add a class, just define the known operations for that class:
public class TypeX implements Operator
{
public void operation1() {
// pretty simple
}
public void operation2() {
// pretty simple
}
}
Now, you have to refactor every class if you add an operation, but adding a class is very easy.
This tradeoff is explained in Clean Code by R. C. Martin (6. Objects and Data Structures, Data/Object Anti-Symmetry):
Procedural code [here: the visitor] makes it hard to add new data structures because all the functions must change. OO code makes it hard to add new functions because all the classes must change.
What you should do
As stated in a #radiodef comment, avoid reflection and other tricks. This will be worse than the issue.
Clearly separate where you really need the visitor pattern, and where you don't. Count classes and operations. I bet that, in most of the cases, you don't need the visitor pattern. (Your managers are probably right!). If you need the visitor pattern in 10 % of the cases, maybe the "additonal overhead of boilerplate code" will be acceptable.
Since several of your TypeX classes are already wrappers, you maybe need to wrap better. Sometimes, one wraps from bottom to top: "My 3rd party class has those methods: I will wrap the methods I need and forget the others. And I will keep the same names to keep it simple." Instead, you have to carefully define the service a TypeX class should provide. (A hint: look in your if ... instanceof ... bodies). A then wrap again the 3rd party libs to provide thoses services.
Really: avoid avoid reflection and other tricks.
What would I do?
You asked in a comment for a pseudo-code, but I can't give it to you since I have a method in mind, not a procedure or an algorithm.
Here's a minimal step by of step of what I would do in such a situation.
Isolate every "big instanceof switch" in a method
That's almost a medical advice! Before:
public void someMethod() {
...
...
if(object instanceof TypeA) {
TypeA typeA = (TypeA) object;
...
...
}
else if(object instanceof TypeB) {
TypeB typeB = (TypeB) object;
...
...
}
...
...
}
After:
public void someMethod() {
...
...
this.whatYouDoInTheSwitch(object, some args);
...
...
}
And:
private void whatYouDoInTheSwitch(Object object, some args) {
if(object instanceof TypeA) {
TypeA typeA = (TypeA) object;
...
...
}
else if(object instanceof TypeB) {
TypeB typeB = (TypeB) object;
...
...
}
}
Any decent IDE will do it for free.
If you are in a case that would need the Visitor pattern
Leave the code as this, but document it:
/** Needs fix: use Visitor Pattern, because... (growing set of operations, ...) */
private void whatYouDoInTheSwitch(Object object, some args) {
...
}
If you want to use polymorphism
The goal is to switch from:
this.whatYouDoInTheSwitch(object, other args);
To:
object.whatYouDoInTheSwitch(this, other args);
You have a little refactoring to do:
A. Create a method for every case in the big switch. All those methods should have the same signature, except for the type of the object:
private void whatYouDoInTheSwitch(Object object, some args) {
if(object instanceof TypeA) {
this.doIt((TypeA) object, some args);
}
else if(object instanceof TypeB) {
this.doIt((TypeB) object, some args);
}
}
Again, any IDE will do it for free.
B. Create an interface with the following method:
doIt(Caller caller, args);
Where Caller is the type of the class you are refactoring (the one that contains the big switch).
C. Make every TypeX implement this interface by converting every doIt(TypeX objX, some args) into a doIt(Caller, some args) method from TypeX. Basically, that is a simple find-replace: replace this by caller and objX by this. But this may be a little more time consuming than the rest.
D. Now, you have:
private void whatYouDoInTheSwitch(Object object, some args) {
if(object instanceof TypeA) {
((TypeA) object).doIt(this, some args);
}
else if(object instanceof TypeB) {
((TypeB) object).doIt(this, some args);
}
}
This is strictly equivalent to:
private void whatYouDoInTheSwitch(Object object, some args) {
if(object instanceof TypeA) {
object.doIt(this, some args);
}
else if(object instanceof TypeB) {
object.doIt(this, some args);
}
}
Because at runtime, the JVM will find the right method for the right class (that's polymorphism!). Thus, this is also equivalent to (if object has one of the enumerated types):
private void whatYouDoInTheSwitch(Object object, some args) {
object.doIt(this, some args);
}
E. Inline the method and you have in your Caller class:
public void someMethod() {
...
...
object.doIt(this, some args);
...
...
}
Actually, this is only a sketch, and many special cases could occur. But it is guaranteed to be relatively fast and clean. It may be done for a selected method only of for all methods.
Be sure to test, if possible, the code after every step. And be sure to choose the right names for the methods.
Seems like polymorphism. Such code could stem from a heterogene set of business object classes, like Excel ReportX, Zip, TableY, and actions like Open, Close, Save and such.
As it is, this kind of programming causes a huge coupling between classes, and has issues with completeness of all cases, extendibility.
In the case of polymorphism the actual wrapper for some bussiness object should provide Actions (Open, Save, Close).
This mechanism is similar to java swing, where an edit field has its list of actions (Cut, Copy, Paste and such), and a tree view an overlapping set of actions. Depending on the focus the actual actions will be installed in the menu actions.
A declarative specification might be in order: say an XML that "holds" beans and their actions.
Should you have some MVC paradigm on the radar, consider the following:
every action could have parameters. Use PMVC (my idea), a Parameters class apart from the Model class, as those infos have a different life cycle, and are constant.
The road hereto could be:
a prototype with two business objects and two actions.
refactoring with one polymorph business object containing all (old code).
slowly moving one class after another to their own business object.
the first removal from the polymorph business object being used to clean up the new architecture.
I would refrain from using inheritance (a BaseDocument with open/save) as this probably does not fit a more heterogeneous reality, and could cause parallel class hierarchies (XDoc with XContainer and XObject).
How it is actually done is still your work. I also would be eager to learn whether there exists an established paradigm.
Asked pseudo-code
One would need a bit of analysis with some prototype made - a proof of concept. However there is a discovery of (dynamic) capabilities/features.
public interface Capabilities {
<T> Optional<T> as(Class<T> type);
}
Add this interface to every case class, and you can do:
void f(Capabilities animal) {
int distance = 45;
animal.as(Flying.class).ifPresent(bird -> bird.fly(distance));
}
The infrastructure would be: first the registration of capabilities and discovery can be placed in a separate class.
/**
* Capabilities registration & discovery map, one can delegate to.
*/
public class CapabilityLookup implements Capabilities {
private final Map<Class<?>, Object> capabilitiesMap = new HashMap<>();
public final <T> void register(Class<T> type, T instance) {
capabilitiesMap.put(type, instance);
}
#Override
public <T> Optional<T> as(Class<T> type) {
Object instance = capabilitiesMap.get(type);
return instance == null ? Optional.empty()
: Optional.of(type.cast(instance));
}
}
Then the legacy classes can be augmented:
/** Extended legacy class. */
public class Ape implements Capabilities {
private final CapabilityLookup lookup = new CapabilityLookup();
public Ape() {
lookup.register(String.class, "oook");
}
#Override
public <T> Optional<T> as(Class<T> type) {
return lookup.as(type); // Delegate to the lookup map.
}
}
/** Extended legacy class. */
public class Bird implements Capabilities {
private final CapabilityLookup lookup = new CapabilityLookup();
public Bird() {
lookup.register(Flying.class, new Flying() {
...
});
lookup.register(Singing.class, new Singing() {
...
});
}
#Override
public <T> Optional<T> as(Class<T> type) {
return lookup.as(type); // Delegate to the lookup map.
}
}
As you can see with Bird the original code would move into the actual class of the interface, here into Bird, as the instance was created in the constructor. But instead of an anonymous class one could make a BirdAsFlying class, a kind of action class in java swing parlance.
An inner class has the advantage to access Bird.this.
The refactoring can be done incrementally. Add Capabilities to all "instanceof" legacy classes. An if-sequence would normally be one interface, but could also be two, or one interface with two methods.

Separate implementations of an interface

I am looking for a technique to have a single entry point for my interface, but where each implementation is handled differently.
Let's show an example.
I have got a couple of implementations of an Instrument-interface. Instruments ofcourse share some similarities (they make music, have something to do with notes and scales) but they are played very differently.
A Musician can play an instrument, and a gifted musician can play several instruments:
public interface Musician {
void play(Instrument instrument);
}
public class GiftedMusician implements Musician {
#Override
public void play(Instrument instrument) {
if (instrument instanceof Guitar) {
play((Guitar) instrument);
} else if (instrument instanceof Bass) {
play((Bass) instrument);
} else if (instrument instanceof Piano) {
play((Piano) instrument);
}
}
public void play(Guitar guitar) {
guitar.strumWithPick();
}
public void play(Bass bass) {
bass.pluckString();
}
public void play(Piano piano) {
piano.pressKey();
}
}
I have found a solution using instanceof but I am not sure if this is the way to go. I am looking for a design pattern or otherwise best practice to handle such a scenario.
Edit:
This example was of course very simple, let's make it a little less obvious. Because, as i said, there are many many kinds of instruments, which are played in different ways. Like a contrabass. How would I implement a Musician that plays regular- and contrabass?
public class Contrabass implements Instrument{
public void play(boolean useBow) {
if(useBow)
playWithBow();
else
pluckWithFingers();
}
}
In my opinion, you should declare the following method in Instrument:
public void play(Musician musician);
You can then implement it differently for each instrument.
For instance:
class Guitar implements Instrument {
#Override
public void play(Musician musician) {
System.out.printf("Musician %s is playing the guitar!%n", musician.getName());
strumWithPick();
}
}
... and so on.
With this example, your GiftedMusician class would make less sense, unless you decide to use composition to associate an Instrument or many to a Musician.
In the latter case, your GiftedMusician would have a constructor overload taking, say, a Collection<Instrument>, whereas your Musician would only have a constructor with a single Instrument.
For instance (with Instrument as abstract class, to add core "functionality" to play):
class Musician {
protected Collection<Instrument> instruments;
Musician(Instrument instrument) {
instruments = new HashSet<Instrument>();
if (instrument != null)
instruments.add(instrument);
}
public String getName() {
// of course
return "J. S. Bach";
}
}
class GiftedMusician extends Musician {
GiftedMusician(Instrument instrument) {
super(instrument);
}
GiftedMusician(Collection<Instrument> instruments) {
super(null);
this.instruments = new HashSet<Instrument>(instruments);
}
}
abstract class Instrument {
protected String name;
public void play(Musician musician) {
System.out.printf("Musician %s is playing %s%n", musician.getName(), name);
}
}
Edit following up question edit.
If you need to parametrize a specific playing technique into your play method, without an overload anti-pattern and returning to the instanceof long list anti-pattern, you've got all the more reason to parametrize play with a Musician.
It's the Musician who decides the technique they want to play with after all.
Once within the play body, you can then adapt the playing logic to something in the lines of musician.getCurrentTechnique().
First of all: You're right when questioning the use of instanceof. It may have some use-cases, but whenever you feel tempted to use instanceof, you should take a step back and check whether your design is really sound.
My suggestions are roughly in line with what Mena said in his answer. But from a conceptual view, I think that the direction of the dependency is a bit odd when you have to write a line like
instrument.play(musician);
instead of
musician.play(instrument);
A phrase like "an instrument can be played" IMHO suggests that the instruments are a parameter of a method, and not the object that the method is called on. They are "passive", in that sense. (One of your comments was also related to this, when you said that "the Instrument-class has an import on Musician", which doesn't seem right). But whether or not this is appropriate also depends on the real use-case. The example is very artificial and suggestive, and this may lead to suggestions for solutions that don't fit in the real world. The possible solutions for modeling this largely vary in the responsiblities, the question "Who knows what?", and how the modeled structures are intended to be used, and it's hard to give a general answer here.
However, considering that instruments can be played, it seems obvious that one could intruduce a simple method bePlayed() in the Instrument interface. This was already suggested in the other answers, leading to an implementation of the Musician interface that simply plays the instrument:
public class GiftedMusician implements Musician
{
#Override
public void play(Instrument instrument)
{
instrument.bePlayed();
}
}
One of the open issues is:
Who (and how) decides whether a musician can play the instrument?
One pragmatic solution would be to let the musician know the instrument classes that he can play:
public class GiftedMusician implements Musician
{
private final Set<Class<?>> instrumentClasses =
new LinkedHashSet<Class<?>>();
<T extends Instrument> void learn(Class<T> instrumentClass)
{
instrumentClasses.add(instrumentClass);
}
void drinkLotsOfBeer()
{
instrumentClasses.clear();
}
#Override
public void play(Instrument instrument)
{
if (instrumentClasses.contains(instrument.getClass())
{
instrument.bePlayed();
}
else
{
System.out.println("I can't play the " + instrument.getClass());
}
}
}
In your EDIT, you opened a new degree of freedom for the design space: You mentioned that the instruments can be played in different ways (like the contrabass, with bow or fingers). This suggests that it may be appropriate to introduce a PlayingTechnique class, as Mena also said in the comments.
The first shot could look like this
interface PlayingTechnique {
void applyTo(Instrument instrument);
}
But this raises two questions:
1. Which methods does the Instrument interface offer?
This question could be phrased in more natural language: What do Instruments have in common?. Intuitively, one would say: Not much. They can be played, as already shown in the bePlayed() method mentioned above. But this does not cover the different techniques, and these techniques may be highly specific for the particular class. However, you already mentioned some methods that the concrete classes could have:
Guitar#strumWithPick()
Bass#pluckString()
Piano#pressKey();
Contrabass#playWithBow();
Contrabass#pluckWithFingers()
So regarding the PlayingTechnique class, one could consider adding some generics:
interface PlayingTechnique<T extends Instrument>
{
Class<?> getInstrumentClass();
void applyTo(T instrument);
}
and have different implementations of these:
class ContrabassBowPlayingTechnique
implements PlayingTechnique<Contrabass> {
#Override
public Class<?> getInstrumentClass()
{
return Contrabass.class;
}
#Override
public void applyTo(Contrabass instrument)
{
instrument.playWithBow();
}
}
class ContrabassFingersPlayingTechnique
implements PlayingTechnique<Contrabass> {
#Override
public Class<?> getInstrumentClass()
{
return Contrabass.class;
}
#Override
public void applyTo(Contrabass instrument)
{
instrument.pluckWithFingers();
}
}
(Side note: One could consider generalizing this even further. This would roughly mean that the Instrument interface would have several sub-interfaces, like StringInstrument and KeyInstrument and WindInstrument, each offering an appropriate set of more specific methods, like
StringInstrument#playWithBow()
StringInstrument#playWithFingers()
While technically possible, this would raise questions like whether a Guitar may be played with the bow, or a Violin may be played with the fingers - but this goes beyond what can seriously be considered based on the artificial example)
The GiftedMusician class could be adjusted accordingly:
public class GiftedMusician implements Musician
{
private final Set<PlayingTechnique<?>> playingTechniques =
new LinkedHashSet<PlayingTechnique<?>>();
<T extends Instrument> void learn(PlayingTechnique<T> playingTechnique)
{
playingTechniques.add(playingTechnique);
}
void drinkLotsOfBeer()
{
playingTechniques.clear();
}
#Override
public void play(Instrument instrument)
{
for (PlayingTechnique<?> playingTechnique : playingTechniques)
{
if (playingTechnique.getInstrumentClass() == instrument.getClass())
{
// May need to cast here (but it's safe)
playingTechnique.applyTo(instrument);
return;
}
}
System.out.println("I can't play the " + instrument.getClass());
}
}
Still, there is a second open question:
2. Who decides (when and how) which PlayingTechique is applied?
In the current form, a gifted musician could learn two playing techniques for the same instrument class:
giftedMusician.learn(new ContrabassBowPlayingTechnique());
giftedMusician.learn(new ContrabassFingersPlayingTechnique());
// Which technique will he apply?
giftedMusician.play(contrabass);
But whether the decision is made by the Musician (maybe based on some "proficiency" that is associated with each technique), or from the outside, will depend on the real-world problem that you are actually trying to solve.
Add method
void play();
to the Instrument interface. Each implementation of it should be calling respective method, e.g.
public class Guitar implements Instrument {
public void play() {
strumWithPick();
}
private void strumWithPick() {
// implementation details here
}
}
Then GiftedMusician#play(Instrument) should be simplified:
public void play(Instrument instrument) {
instrument.play();
}
Add the method void play(); to your interface without any parameters. What you want to do is exhibit the behaviour of polymorphism.
So instead of using instanceof to check for each implementation, you have it in your interface as just void play();. Hence, whenever the interface is implemented, the play() method can be overriden and implemented specifically for the given class e.g. your Bass class.
It seems code examples have already been given in other answers but specifically look up the term polymorphism in the context of OOP. In particular this question has some good answers: What is polymorphism, what is it for, and how is it used?

Best way to differentiate between class types for different handling

I wanted to know what are the advantages / disadvantages of using each of the following ways to differentiate between sub-classes of the main parent class and handle them differently. I know this is pretty basic, but i couldnt find a full comparison between these ways anywhere.
For example:
- I have a Payment super abstract class and two extending classes OneTimePayment and Subscription
- I have a method switchPaymentState that should handle each one of these types differently
Option 1: Using instanceof
public void switchPaymentState(Payment payment) {
if(payment instanceof OneTimePayment) {
//do something
} else if(payment instanceof Subscription) {
//do something else
}
}
Option 2: Using enum type argument (or other...)
public enum PaymentType {
ONE_TIME_PAYMENT,
SUBSCRIPTION;
}
public abstract Payment(PaymentType type) {
this.type = type;
}
public OneTimePayment() {
super(ONE_TIME_PAYMENT);
}
public Subscription() {
super(SUBSCRIPTION);
}
and then:
public void switchPaymentState(Payment payment) {
switch(payment.type) {
case ONE_TIME_PAYMENT:
//do something
break;
case SUBSCRIPTION:
//do something
break;
}
}
Option 3: Using overload methods
public void switchPaymentState(OneTimePayment payment){
//do something
}
public void switchPaymentState(Subscription payment){
//do something
}
So, which is the best way to go (or a complete other way?) and why?
EDIT:
The operations i need to do based on the class type are NOT operations on the class itself, i need to take some data form the payment and send it via other services, so solutions like implementing this functionality inside the classes and calling it regardless of the type, will unfortunately not help in this case. Thanks!
The most modular way would be to use overriding.
You'll have a single switchPaymentState method which accepts the base type - Payment - and calls a method in the Payment class to do the handling. That method can be overridden in each sub-class of Payment.
public void switchPaymentState(Payment payment)
{
payment.handlePayment();
}
Your switchPaymentState method doesn't have to know which sub-classes of Payment exist, and it doesn't have to change if you add new sub-classes tomorrow.
Your option 3 will in many cases not work, because overloading is resolved atcompile-time rather than at run-time. If the type of your references is Payment, it is not possible to use overloading.
In terms of object-oriented design, using overridden methods is the "cleanest" method. However, it has the disadvantage that similar functionality is spead over multiple classes, whereas in the switch and instanceof solutions everything is together.
An alternative that offers the best of both worlds is the so-called Visitor Pattern. You create an interface PaymentVisitor with for each class you want a handle a method, as follows:
interface PaymentVisitor {
void visitOneTimePayment(OneTimePayment payment);
void visitSubscription(Subscription payment);
}
Then in you abstract superclass you add a method visit:
abstract class Payment {
...
abstract void callVisitor(PaymentVisitor visitor);
}
Which you implement in all you subclasses as follows:
class OneTimePayment {
...
#Override void callVisitor(PaymentVisitor visitor) {
visitor.handleOneTimePayment(this);
}
}
class Subscription {
...
#Override void callVisitor(PaymentVisitor visitor) {
visitor.handleSubscription(this);
}
}
Now, in all cases where you would otherwise write something like (in pseudo-Java):
switch (type of x) {
case OneTimePayment:
// Code
break;
case Subscription:
// Code
break;
}
You can now write, cleanly and type-safe:
x.callVisitor(new PaymentVisitor() {
#Override void handleOneTimePayment(OneTimePayment payment) {
// Code
}
#Override void handleSubscription(Subscription payment) {
// Code
}
});
Note also that the visitor is implemented in an inner class, so you still have access to all (effectively) final variables defined in the method body.
I think the switch is a bit of an anti-pattern regardless of how you do it. The more standard OO way would be to implement the same method or methods in both of the subclasses, and let each class manage things as appropriate. In other words
abstract class Payment {
abstract void processPayment(BigDecimal amount);
abstract void processRefund...
}
class OneTimePayment extends Payment {
void processPayment(BigDecimal amount){... }
void processRefund...
}
etc.
Also, unless you're reusing a considerable amount of code in the super class, consider an interface-based implementation instead of subclassing.

instanceof vs boolean type checking

I have an interface called Section and MapSection which extends section. I have a list of Sections and if it is a MapSection I need to do some additional processing. I can thing of two ways to handle this. I can add a boolean isAMapSection() to the Section interface but that leads to alot of isA.. if I add more types. The other way I could think of is instanceof check but my OOP senses think this is not great either.
curSection instanceof MapSection
which one of these is the right way? or is there another way?
As mentioned above by Oliver Charlesworth's comment, you could use a Visitor Design Pattern to give your code to do different actions depending on the type involved, without having to use a bunch of instanceof's or class equals.
For example, say you have two similar interfaces, Section and MapSection, where for grins will give MapSection one additional method:
interface Section {
void someMethod();
void accept(SectionVisitor visitor);
}
interface MapSection extends Section {
void additionalProcessingMethod();
}
We'll also give Section the accept(...) method to allow action by a Visitor of type SectionVisitor whose interface looks like:
interface SectionVisitor {
void visit(Section section);
void visit(MapSection mapSection);
}
The visit method will hold code that knows which methods to call depending on the type passed into it.
A very simple concrete example could look like:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class VisitorTest {
public static void main(String[] args) {
Random random = new Random();
List<Section> sectionList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Section section = random.nextBoolean() ? new ConcreteSection() : new ConcreteMapSection();
sectionList.add(section);
}
SectionVisitor visitor = new ConcreteSectionVisitor();
for (Section section : sectionList) {
section.accept(visitor);
}
}
}
interface Section {
void someMethod();
void accept(SectionVisitor visitor);
}
interface MapSection extends Section {
void additionalProcessingMethod();
}
interface SectionVisitor {
void visit(Section section);
void visit(MapSection mapSection);
}
class ConcreteSection implements Section {
#Override
public void someMethod() {
System.out.println("someMethod in ConcreteSection");
}
#Override
public void accept(SectionVisitor visitor) {
visitor.visit(this);
}
}
class ConcreteMapSection implements MapSection {
#Override
public void someMethod() {
System.out.println("someMethod in ConcreteMapSection");
}
#Override
public void additionalProcessingMethod() {
System.out.println("additionalProcessingMethod in ConcreteMapSection");
}
#Override
public void accept(SectionVisitor visitor) {
visitor.visit(this);
}
}
class ConcreteSectionVisitor implements SectionVisitor {
#Override
public void visit(Section section) {
section.someMethod();
}
#Override
public void visit(MapSection mapSection) {
mapSection.someMethod();
mapSection.additionalProcessingMethod();
}
}
Best way might be to add a method "additionalProcessing" to Section. Implement this method to do your additional processing in MapSection, and leave it blank in your other implementations
Sometimes it's fine to have an isXXX method (and the corresponding asXXX method is nice too), but it really depends on how open-ended your object hierarchy is.
For example in StAX the XMLEvent interface will have descendants that represent the different types of events that can come from an XML document. But the list of those types is closed (no-one's going to radically change the XML format any time soon) and very short (there are about 10 different types of events in the StAX API), so it's fine. These interfaces also define the primary nature of their implementations, you wouldn't realistically just tag an object with an XMLEvent interface like you do with Serializable or Iterable.
If your interface is more "behavioural" (for want of a better word), more optional (like Comparable) or too open-ended (like LayoutManager), things like the visitor or the strategy pattern may be more appropriate.
Judging just by the names Section and MapSection, your model seems to belong to the first category but really only you can make that decision. What I definitely wouldn't do is leave it to the client of the code to fool around with instanceof calls. One way or another the solution should be part of Section.

Categories