I should use and name a design pattern for following problem:
I have separate interfaces: Basic, Complex. All classes implement Basic. Some of the classes implement Complex but they have to inherit from Abstract class.
I was thinking about decorator but I don't know if I'm right.
Code is in Java.
I think something like Builder design pattern can be good for this case:
first Create an interface for the Basic
public interface Basic{
public void basicOp();
}
second: create an interface for the Complex one:
public interface Complex{
public void complexOp();
public Basic basicOp();
}
Third: create required classes which implements basic interface:(Class2)
public class abstractBasicA implements Basic {
#Override
public void basicOp() { ... }
}
fourth: create abstract required classes for complex interface
public abstract class AbstractClassComplexA implements Complex{
#Override
public complexOp() { ... }
#Override
public abstract Basic basicOp(){...}
}
fifth: create all other classes which extends above abstract class(Class3, Class4, Class5).
I think you should go with decorator pattern and use composition. A Complex should have a Basic member, which could manage the Basic part of the Complex type.
Below a short example.
package main;
public class Main {
public static void main(String[] args) {
Basic basic = new BasicImpl();
basic.basicOp();
// main.BasicImpl.op()
Complex ca = new ConcreteComplexA(basic);
ca.basicOp();
ca.complexOp();
// main.BasicImpl.op()
// main.ConcreteComplexA.complex()
Complex cb = new ConcreteComplexB(basic);
cb.basicOp();
cb.complexOp();
// main.BasicImpl.op()
// main.ConcreteComplexB.complex()
}
}
interface Basic {
void basicOp();
}
interface Complex extends Basic {
void complexOp();
}
class BasicImpl implements Basic {
#Override
public void basicOp() {
System.out.println("main.BasicImpl.basicOp()");
}
}
abstract class AbstractComplex implements Complex {
private final Basic basic;
public AbstractComplex(Basic basic) {
this.basic = basic;
}
#Override
public void basicOp() {
basic.basicOp();
}
}
class ConcreteComplexA extends AbstractComplex {
public ConcreteComplexA(Basic basic) {
super(basic);
}
#Override
public void complexOp() {
System.out.println("main.ConcreteComplexA.complex()");
}
}
class ConcreteComplexB extends AbstractComplex {
public ConcreteComplexB(Basic basic) {
super(basic);
}
#Override
public void complexOp() {
System.out.println("main.ConcreteComplexB.complex()");
}
}
If you want clean subtypting, you have to enforce behavioral conformance, i.e. adhere to all the invariants of the type (and of its methods) your inheriting from, you need Basic to extend Complex, but that feels counter-intuitive very often. But only if Complex redefines/specializes the inherited methods.
Sometimes it is best to make use of composition instead of inheritance. So instead of relying on a lot of subclasses, pull out the behaviour in an independent structure and inject it. Design patterns that could be playing here would be strategy and dependency injection (inversion of control).
Deep class hierarchies are often a smell indicator and often you run into problems since Java doesn't support trades and you get code duplication if you need the same behavior in different classes that don't share the same ancestor.
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();
}
}
The abstract factory pattern is useful when we have families of related classes, and we want to instantiate them without relying on the implementation. However, what's wrong with using the factory method pattern in such a situation?
Let's say that we want to construct cross-platform UI elements, e.g. TextBox and Button for Windows and macOS and treat them abstractly. This is the typical situation in which we use the abstract factory pattern, and we can do so by defining the following:
AbstractUIElementsFactory interface
WindowsUIElementsFactory implements AbstractUIElementsFactory
MacUIElementsFactory implements AbstractUIElementsFactory
TextBox abstract class
MacTextBox extends TextBox
WindowsTextBox extends TextBox
Button abstract class
MacButton extends Button
WindowsButton extends Button
and the application would decide which concrete factory to create (based on some OS discovery mechanism) and pass it to a UIApplication class, which instantiates a TextBox and a Button, and calls display on them (which are abstract methods that simply return a String).
The code for this situation:
package abstractFactory;
abstract class Button {
public abstract void display();
}
class MacButton extends Button {
public void display() {
System.out.println("macButton");
}
}
class WindowsButton extends Button {
#Override
public void display() {
System.out.println("winButton");
}
}
abstract class TextBox {
public abstract void display();
}
class MacTextBox extends TextBox {
#Override
public void display() {
System.out.println("macTextBox");
}
}
class WinTextBox extends TextBox {
#Override
public void display() {
System.out.println("winTextBox");
}
}
interface UICreatorAbstractFactory {
Button getButton();
TextBox getTextBox();
}
class MacFactory implements UICreatorAbstractFactory {
#Override
public Button getButton() {
return new MacButton();
}
#Override
public TextBox getTextBox() {
return new MacTextBox();
}
}
class WindowsFactory implements UICreatorAbstractFactory {
#Override
public Button getButton() {
return new WindowsButton();
}
#Override
public TextBox getTextBox() {
return new WinTextBox();
}
}
class UIApplication {
private UICreatorAbstractFactory factory;
UIApplication(UICreatorAbstractFactory _factory) {
factory = _factory;
}
public void displayUI() {
factory.getButton().display();
factory.getTextBox().display();
}
}
public class Main {
public static void main(String[] args) {
new UIApplication(new MacFactory()).displayUI();
}
}
This implementation allows us to get UI elements transparently from factory implementations and also UI elements implementations, which is largely why we would use the pattern.
Using the same TextBox, Button, and their derivatives, we can have a factory method implementation with two factory methods in the creator, UICreator, each of which returns an abstract UI element. And we derive the creator and make two specializations WindowsUICreator, and MacUICreator, and each of which returns the appropriate concrete UI element, as follows:
abstract class UICreator {
public void displayUI() {
getButton().display();
getTextBox().display();
}
protected abstract Button getButton();
protected abstract TextBox getTextBox();
}
class WindowsUICreator extends UICreator {
#Override
protected Button getButton() {
return new WindowsButton();
}
#Override
protected TextBox getTextBox() {
return new WinTextBox();
}
}
class MacUICreator extends UICreator {
#Override
protected Button getButton() {
return new MacButton();
}
#Override
protected TextBox getTextBox() {
return new MacTextBox();
}
}
public class Main {
public static void main(String[] args) {
new MacUICreator().displayUI();
}
}
What are the downsides of this design? I believe it provides the needed decoupling by not having to deal with any concrete classes, and also provides the proper extensibility in the sense that we can introduce new UI elements and give them new factory methods, or newly supported OSs and implement concrete creators for them. And if we can use the factory method pattern in the exact situation the abstract factory pattern was designed for, I don't understand why do we have it at all?
They are both about creating new objects but the factory method is used to create one product only while the Abstract Factory is about creating families of related or dependent products.
In the Abstract Factory pattern, a class delegates the responsibility of object instantiation to another object via composition, whereas the Factory Method pattern uses inheritance and relies on a subclass to handle the desired object instantiation.
I would like to show you an image from Saurav Satpathy's blog here which quickly can explain why you want abstract factory over factory method at times.
The argument for dependency injection and collection of related objects makes a lot of sense and here is a coded example by a great creator The Refactoring Guru on Abstract Factory and here is his example on factory method. The main difference between the examples in my opinion is the abstract factory better depicts the complexity of factories that create multiple types of objects. Additionally, it effectively divides the code in more classes, making each class simpler to understand (but creating more classes in total, of course).
Keep in mind this is not a very in depth analysis as of now, I want to see other people's opinions on the matter and give it some time to think for myself. I may come back in a couple of days with an edit (currently a bit busy, but I sneaked a quick opinion for you)
Edit #1 Inheritance
"Favor object composition over class inheritance. Inheritance breaks encapsulation, implement abstract classes, do not inherit concrete classes! - The Gang of Four on Design Patterns"
So object inheritance if you read the GoF's book: "Design Patterns Elements of Reusable Object-Oriented Software" is discouraged, especially when systems become more and more complex or higher in scope. Edit influenced by #FelipeLlinares great point indeed.
I am trying to implement Template method pattern, but I need a slight variation that I don't think is best practice.
I have the following structure of classes
abstract class AbsClass {
public void algorithm(){
step1();
step2();
}
private void step1() {
//implementation
}
protected abstract void step2();
}
class A extends AbsClass {
protected void step2() {
// With implementation
}
}
class B extends AbsClass {
protected void step2() {
// No implementation needed
}
}
In the real case I have like 4 classes, and one of them doesn't need to have implementation for the second step. I don't think to leave the method empty would be good practice. I was thinking to put a comment(saying there is no need for implementation) in it, but I don't this would be the right solution.
Is there another approach I am not seeing?
We should not Force a design pattern. Here if we prefer Composition over inheritance then its better.
The code present in the question we have a method defined in a class but actually method has no behavior. Forcing a method in a class where it should not belomg to is not a good idea.
Below is one such possible implementation where you would not force a method to a class if it does not belong to it. Below is based on Strategy patter, but still I would say follow design principles and let the pattern itself suit your problem and do not force pattern to fit your solution.
public class AlgorithmClass {
private Strategy strategy;
public void setStrategy(Strategy strategy){
this.strategy = strategy;
}
public void algorithm(){
step1();
step2();
}
private void step1() {
//implementation
}
private void step2(){
if(this.strategy != null){
this.strategy.execute();
}
}
}
public interface Strategy{
public void execute();
}
public class Strategy1 implements Strategy{
public void execute(){
//implement your one of the stategies for step 2
}
}
public class Strategy2 implements Strategy{
public void execute(){
//implement your another stategy for step 2
}
}
I agree with #Vinay Avasthi's answer but I want to reinforce it.
Hook Method
Hook methods are defined in the base class and are a default implementation. And these can be overridden - they don't have to.
From Template-Method-Pattern Wikipedia page:
Template method's abstract class may also define hook methods that may be overridden by subclasses. These have a no-op implementation in the abstract class, but provide a "hook" on which to "hang" implementations.
Improvement
What you should do is leave a comment in the method body like // empty method body so that someone reading your code (and maybe your self) knows that this method has not been forgotten
Java's Default Methods
There is a second way to implement the Template-Method-Pattern in Java. Since Java 8 it is possible to have default method implementations in an interface.
If your methods do not depend on state it could look like:
interface AbsClass {
default void algorithm(){
step1();
step2();
}
default void step1() {
// implementation or empty
}
default void step2() {
// empty body in default case
}
}
class B implements AbsClass { }
I think it is absolutely fine. If the default behavior of step2 is to do nothing, then you can have an empty method in base class and override in child classes.
I am just wandering if following is an odd behaviour.
public interface TestInterfaceTwo {
public void sayBye();
}
public interface TestInterfaceOne {
public void sayHI();
}
public abstract class TestIntefaceClass implements TestInterfaceOne, TestInterfaceTwo {
#Override
public void sayHI() {
System.out.println("HI");
}
#Override
public void sayBye() {
System.out.println("Bye");
}
}
public class InterfaceImplementer extends TestIntefaceClass{
#Override
public void sayHI() {
System.out.println("SAY HI");
}
}
public static void main(String[] args) {
InterfaceImplementer impl = new InterfaceImplementer();
TestInterfaceOne impl1 = new InterfaceImplementer();
TestInterfaceTwo impl2 = new InterfaceImplementer();
TestIntefaceClass impl3 = new InterfaceImplementer();
impl.sayHI();
impl.sayBye();
impl1.sayHI();
impl2.sayBye();
impl.sayBye();
impl3.sayBye();
impl3.sayHI();
}
These calls result the following
SAY HI
Bye
SAY HI
Bye
Bye
Bye
SAY HI
I needed to know if interface instances inherit only the expected behavior from the interface or if it inherits the abstract class. It seems it does the latter and I would like to know an explanation for this and if it is bug Or a feature. :)
This works as expected. I am not entirely sure what is that confuses you.
I needed to know if interface instances inherit only the expected behavior from the interface or if it inherits the abstract class. It seems it does the latter and I would like to know an explanation for this and if it is bug Or a feature. :)
Interfaces don't implement any 'behaviour' (although Java 8 provides default methods) and you can't instantiate one. All those instances you're creating are class instances - in your case, instances of InterfaceImplementer. So let's look at this class and its parent:
TestIntefaceClass implements two interfaces and their methods. Nothing special here.
InterfaceImplementer extends TestIntefaceClass class, it inherits the implementation of sayBye() but it provides its own implementation of sayHi().
Now the following (and the other similar examples from your code)
TestInterfaceOne impl = new InterfaceImplementer();
creates an instance of InterfaceImplementer, as you can see on the right hand side. Thus the implementations that will be used when calling sayHi() and sayBye() will be the ones that Interfaceimplementer overrides / inherits.
LE: This link will probably be useful to you. It discusses using interfaces as types, which is what you're doing.
the "new InterfaceImplementer()" is giving you exactly that ... its just you are decalring them as the various ways .... it's working as expected
is this an example of TemplateMethod Pattern??
public abstract class Character{
public final void useWeapon(){
useBusterSword();
useMateriaBlade();
useUltimateWeapon();
}
public abstract void useBusterSword();
public abstract void useMateriaBlade();
public abstract void useUltimateWeapon();
}
public class Cloud extends Character{
public void useUltimateWeapon() {
System.out.println("Change Weapon to Ultima Weapon");
}
public void useBusterSword() {
}
public void useMateriaBlade() {
}
}
public class TestGame {
public static void main(String[] args){
Character cloud = new Cloud();
cloud.useWeapon();
}
}
If so then what is the advantage of using this pattern than strategy pattern??
Strategy Pattern
public class Character {
WeaponBehavior w;
public void setWeaponBehavior(WeaponBehavior wb){
w = wb;
}
public void useWeapon(){
w.useWeapon();
}
}
public class Cloud extends Character{
public Cloud(){
w = new UltimaWeapon();
}
}
public interface WeaponBehavior {
public void useWeapon();
}
public class UltimaWeapon implements WeaponBehavior {
public void useWeapon() {
System.out.println("Change Weapon to UltimaWeapon");
}
}
public class BusterSword implements WeaponBehavior {
public void useWeapon() {
System.out.println("Change Weapon to MateriaBlade");
}
}
public class MateriaBlade implements WeaponBehavior {
public void useWeapon() {
System.out.println("Change Weapon to MateriaBlade");
}
}
public class TestGame {
public static void main(String[] args){
Character c = new Cloud();
c.useWeapon();
}
}
What I noticed is Strategy pattern encapsulate what varies unlike TemplateMethod Pattern lets the subclassed handles what varies.
Strategy pattern defines a family of algorithms and makes them interchangeable. Client code can use different algorithms since the algorithms are encapsulated.
Template method defines the outline of an algorithm and lets subclasses part of the algorithm's implementation. So you can have different implementations of an algorithms steps but retain the algorithm's structure
So as you can see the intent is different in each pattern. So it is not a matter of advantage of one over the other.
Yes you can use strategy pattern instead of template method but in special case you will repeat algorithm logic.
The best use case for template method to replace some abstract method by specific implementation.
E.g. You want to cook smth and your recipe is:
take ingridients
put them into
heat
give coocked food to smbd
In java recipe is just method in some Recipe class
void cook(){
takeIngridients();
putIt(); // abstract
heat(); //abstract
giveFood();
}
You create PanRecipe class extends Recipe and implement abstract methods to use pan.
Another class can be GrillRecipe and implement methods to use grill. Now you can just call it by grillRecipe.cook(), and instead of strategy pattern don't need to copy implementation of repeated methods takeIngridients and giveFood.
Template method pattern is useful when you want to use some parent class's fields and when your implementation is not really a whole algorithm but only some 'logic' very specific to your hierarchy of classes.
On the other hand, when you find out that your template methods implementations are redundant or leads to duplication code across several subclasses of the same tree, prefer Strategy pattern so that your code will be factorized.
Also, template method working by the way of subclassing, you can't change your behaviour at runtime whereas with Strategy pattern, all you have to do is to use setter to change your behaviour whenever you wish.
In all other cases, those two patterns are very similar and you can often choose for the one you like.
Similarities:
Both Template method & Strategy are behavioural patterns.
Both patterns are used to change an algorithm by sub classes but with a difference - Partial or full
For better understanding of these two features, we have to understand core differences in implementation of these two patterns.
Core Differences:
Template method uses Inheritance and Strategy uses composition
The Template method implemented by the base class should not be overridden. In this way, the structure of the algorithm is controlled by the super class, and the details are implemented in the sub classes
Strategy encapsulates the algorithm behind an interface, which provide us ability to change the algorithm at run time
Related posts:
Real World Example of the Strategy Pattern
Template design pattern in JDK, could not find a method defining set of methods to be executed in order
Have a look at Template method and Strategy articles for better understanding.