Design Pattern – Strategy

Hello, how are you?

I will post here some design patterns of the study I am doing about this subject. The base book to this study will be Head First – Design Patterns. I will describe in here the same patterns that we can find in the book, but I will be using different samples and adding more material about this subject as soon it is possible.

Let us use this user case: “An internet site that sells toys cars is receiving a lot of customer visitors every day and becoming more famous. Its investors want more; they want that the site provides to the customers the simulations of the toy car actions.”

Check below our class model (there are others sub classes of ToyCar that are not described below):

Design Pattern - Strategy

The investors want that the car perform the action of starting the engine, to the customers may hear the engine sound. To accomplish this, the solution that it is “the most useful, fastest and quickest” may be to apply some changing in the super class. What of bad could come of using this solution that the Java gives us? Any change in the super class ToyCar will be reflected to all sub classes, and all sub classes will have the same behavior! We just have to create a method to start the engine (“startEngine()”) and our problem will be solved:

Design Pattern - Strategy

The team was very happy with the result of this new functionality that was delivered on time. Now the customers can hear the engine sound. BUT, after a phone call it was possible to see that something bad happened. One of the investors saw something in our application that should never happen, a wood car starting its engine. Why this happened? Let us see our model:

Design Pattern - Strategy

Our wood car, that also has ToyCar as super class, received the method to start the engine when a wood car does not have an engine. What could we do to solve this problem? We could just override the method:

    @Override
    public boolean startEngine() {
        // Do nothing
    }

Would the above code be the best solution? Let us suppose that we have a sub class of ToyCar, a metal car (“MetalCar”) where we would have to override the method too. By doing this method overriding in all classes methods we are increasing our project complexity. And each time, that a new ToyCar sub class is created and this sub class should not have the method startEngine() implemented, we would have to override this method also.

So, which solution would be the best one here? Let us apply the first pattern principle of this study:
“Identify everything that changes and isolate it from what does not change.”
What is the meaning of this? Think about an engine behavior that will be present in one class and other different engine behavior that should be present in another class; we could isolate this behavior from our ToyCar class. Instead of letting our class ToyCar handling this behavior, why do not delegate it? Here it come our second pattern principle:
“Program to an interface”
This principle is nothing more than: use all benefits from super class. Imagine if we have an interface with a visible method, our class will not care with which behavior the interface method has. Let us create an interface to handle this engine behavior:

Design Pattern - Strategy

Bellow you can check how our classes will be implemented. First the class ToyCar, then Mercedes and WoodCar:

// Interface and Engine Behavior implementations

public interface EngineBehavior {
    public boolean startEngine();
}

public class NoEngineBehavior implements EngineBehavior {

    @Override
    public boolean startEngine() {
        System.out.println("No engine to turn on");
        return true;
    }
}

public class RegularEngineBehavior implements EngineBehavior {

    @Override
    public boolean startEngine() {
        System.out.println("Engine On");
        return true;
    }
}

public class PowerfulEngineBehavior implements EngineBehavior {
    
    @Override
    public boolean startEngine() {
        System.out.println("Powerfull Engine On");
        return true;
    }
}

// Our Classes Implmentatioins
public class ToyCar {
    private int doorTotal;
    private int maxSpeed;
    protected EngineBehavior engineBehavior;
    // Others attributes
    
    public ToyCar(){
        engineBehavior = new RegularEngine();
    }
    
    public void startEngine(){
        engineBehavior.startEngine();
    }
    
    // Others methods
}

public class Mercedes extends ToyCar {
    
    public Mercedes(){
        engineBehavior = new PowerfulEngineBehavior();
    }
    
    @Override
    public void startEngine(){
        engineBehavior.startEngine();
    }    
}

public class WoodCar extends ToyCar {
    
    public WoodCar(){
        engineBehavior = new NoEngineBehavior();
    }
    
    @Override
    public void startEngine(){
        engineBehavior.startEngine();
    }
}

I know that we could change the way that our interface is receiving its implementation (“engineBehavior = new NoEngineBehavior();”) and another “upgrades” about patterns, but this refactoring is subject to another posts.

You may think: “Wait a minute, even if I do comment the method startEngine() or put the code engineBehavior = new NoEngineBehavior(); I still have “duplicated code” in my system!” Think with me about this next investor requirement: “When we call the method startEngine() in a type of ToyCar that does not have an engine, we would have to register this action in a log”. If you notice how our classes are implemented now (WoodCar, and all others MetalCar, BambooCar), we would have to change only the method startEngine() in our class NoEngineBehavior. All classes that do not have an engine behavior would be with a correct functioning.

Final considerations:

  • The class name should indicate a noun. Things like: “Car”, “House”, “Computer”, etc. In the user case that we simulated today this behavior is like our noun. It is a class that handles a behavior pattern.
  • Program to an interface – this principle does not necessarily means that we have to create an Interface, but it means always program to a super type. You should always program to a super type like a regular Class (POJO), Abstract Class and Interface. You must decide the best type for your system and implement it. In the book Head First – Design Patterns the authors make this explanation very clear. Do not mistake this principle that says: “always code for a super type” with “always create an interface”. A super type will be the best solution to your design problems in like 99% of the situations.
  • We just studied another project Principle:
    “Give priority to composition rather than inheritance”.

As we saw in our user case today, we used an interface to create the composition. Using composition in our system will make our job easier.

    Design Pattern: Strategy
    Studied Principles:

  • Identify everything that changes and isolate it from what does not change.
  • Program to an interface.
  • Give priority to composition rather than inheritance.

I hope this post might be able to help you.

If you have any questions or ideas to share just leave your comment.

See you soon.

Leave a Comment