In short, I'd like to be able to group class instances by a superclass which does not implement a certain interface. But from the set of instances I'd like to call methods from the interface on those instances that implement that interface.
Some example code which might explain it.
class Building{
String c = "white";
Building(){
}
void printColor(){
println("The building is " + c);
}
void paint( String c ){
this.c = c;
}
void printBuildQuality(){
println("The build quality is average");
}
}
class SturdyFactoryBuilding extends Building implements Factory{
SturdyFactoryBuilding(){
super();
}
void printBuildQuality(){
println("The build quality is sturdy");
}
void printFactoryOutput(){
println("This factory makes stuff");
}
}
class ShakyFactoryBuilding extends Building implements Factory{
ShakyFactoryBuilding(){
super();
}
void printBuildQuality(){
println("The build quality is shaky");
}
void printFactoryOutput(){
println("This factory makes slightly different stuff");
}
}
public interface Factory{
public void printFactoryOutput();
}
Building building = new SturdyFactoryBuilding();
building.printBuildQuality();
building.printColor();
building.paint("bright red");
building.printColor();
building.printFactoryOutput();
Is there a way I can achieve this, perhaps by having an 'isFactory' flag in the superclass.
Thanks.
I think you'll have to make a trade-off: Either you accept some anti-pattern or you open up you Building "interface" to act as an Adapter:
class Building implements Factory{
// the other building stuff
#Override
public void printFactoryOutput(){ /* NO OP */ }
}
Then you can call printFactoryOutput on all Buildings having no effect up to this point.
Since your Factory-implementations extend Building they automatically inherit the NOOP-Implementation. But since you override it:
class ShakyFactoryBuilding extends Building implements Factory{
ShakyFactoryBuilding(){
super();
}
#Override
public void printBuildQuality(){
println("The build quality is shaky");
}
#Override
public void printFactoryOutput(){
println("This factory makes slightly different stuff");
}
}
... you have the desired result.
Drawback is of course that all Buildings do have the printFactoryOutput visible. But that's the trade-off I was talking about. If this is not acceptable, you'll have to completely reconsider your design.
To make it clear that a Building that is not a Factory shall not be called that Method on, you could throw an UnsupportedOperationException in Building, but that would force try/catch blocks everywhere in your code. You could as well return a boolean: default=false and returning true if in fact a factory ... There are plenty possibilities.
You could also change your design to use composition over inheritance.
I think you're getting the message that this is a bad idea. It violates generally accepted object oriented design principles. That said, there are several ways to go about it, some less odious than others.
Just cast it
The simplest thing to do is something like this:
if (building instanceof Factory)
((Factory)building).printFactoryOutput();
You're checking to see whether it's a Factory, then invoking the Factory-specific method after casting. It's a straightforward (and therefore easily understood) way of implementing a bad design.
Make Building aware of Factory
This has issues in that there is currently no necessary relationship between Building and Factory, but such a relationship might help you along.
class Building {
// ...
Factory adaptToFactory() {
return null;
}
}
class SturdyFactoryBuilding ... {
// ...
#Override
Factory adaptToFactory() {
return this;
}
}
Similarly for ShakyFactoryBuilding.
Then you could write
Factory f = building.adaptToFactory();
if (f != null)
f.printFactoryOutput();
More general adapter
If you're doing a lot of this kind of thing, you could make it into a pattern that you apply wherever needed. (Eclipse, for example, uses adapters all over the place.)
interface Adaptable {
<T> T adapt(Class<T> clazz);
}
class Building implements Adaptable {
// ...
#Override
<T> T adapt(Class<T> clazz) {
if (clazz.isInstance(this)) {
return clazz.cast(this);
}
return null;
}
}
Then you'd write
Factory f = building.adapt(Factory.class);
if (f != null)
f.printFactoryOutput();
There are still more places to go with this, but this is far enough for this question, I think.
Related
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();
}
}
There are defensively coded libraries like vert.x. Using interface with static factory way to return implementation. Developer could use their implementation, but when it is not exactly what is needed - it is not possible to extend it. Unfortunatelly, it even bind implementation into interface. Why?
What is recomended way to extends such classes? There has to be other way than copy whole class and rewrite only few needed lines...
E.g.: vert.x implementation of io.vertx.ext.web.handler.CorsHandler
public interface CorsHandler {
static CorsHandler create(String allowedOriginPattern) {
return new CorsHandlerImpl(allowedOriginPattern);
}
...
}
public class CorsHandlerImpl implements CorsHandler {
private boolean isValidOrigin(String origin) {
}
...
}
public class MyCorsHandler implement/extends CorsHandler/impl {
#Override
protected boolean isValidOrigin(String origin) {
// my changes
}
}
It is possible to wrap a class instead of extending it and change only methods that need a different implementation.
This solution is called Adapter Pattern:
In software engineering, the adapter pattern is a software design pattern (also known as Wrapper, an alternative naming shared with the Decorator pattern) that allows the interface of an existing class to be used as another interface.1 It is often used to make existing classes work with others without modifying their source code.
Consider that extending existing classes written by others is not a good idea generally. Infact in a following release their internal implementation can change and that changes can be reflected on extended classes changing their behaviour in a way that sometime is not predictable.
Here an example showing that:
Imagine that you need to extend a ArrayList with a custom implementation to log all added items.
Actually you can rewrite the add and addAll methods as follow:
public void add(E e) {
System.out.println("add item " + e);
super.add(e);
}
public void addAll(Collection<? extends E> c) {
for (E e : c) {
System.out.println("add item " + e);
}
super.addAll(c);
}
This works because the internal implementation of addAll don't call add. But if the implementation of addAll changes with a loop over the collection c that call add for each element your code doesn't work. So changing the base class will change the behaviour of your derived class.
In case of CorsHandler, I would go with extending the Impl and overriding the handling method:
class MyCorsHandler extends CorsHandlerImpl {
public MyCorsHandler(String allowedOriginPattern) {
super(allowedOriginPattern);
}
#Override
public void handle(RoutingContext context) {
HttpServerRequest request = context.request();
HttpServerResponse response = context.response();
String origin = context.request().headers().get(ORIGIN);
if (origin == null) {
// Not a CORS request - we don't set any headers and just call the next handler
context.next();
} else if (isMyValidOrigin(origin)) {
context.next();
} else {
super.handle(context);
}
}
private boolean isMyValidOrigin(String origin) {
// Do something there
return false;
}
}
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?
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.
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.