The Strategy pattern is a behavioral design pattern that enables an object, called the context, to vary its behavior by delegating it to a family of algorithms, called strategies. These algorithms are interchangeable and can be switched at runtime. The Open/Closed Principle (OCP) is a principle in object-oriented design that states that software entities should be open for extension but closed for modification.
Combining the Strategy pattern with the Open/Closed Principle results in flexible and extensible systems because new strategies can be added without modifying the existing codebase, thereby avoiding the risk of introducing new errors or breaking existing code. Furthermore, this approach allows for the creation of new behaviors without recompiling the context or other clients that use it.
To implement this, we start by creating an interface, called the strategy interface or strategy family, that defines the common behavior expected of all strategies. Each strategy then implements this interface and provides its own implementation of the behavior. The context delegates the behavior to a strategy object, which means that the context can use any strategy object that conforms to the strategy interface. New strategies can be added without modifying the existing codebase by simply creating a new class that implements the strategy interface.
Java code example:
public interface Strategy {
void doSomething();
}
public class ConcreteStrategy1 implements Strategy {
@Override
public void doSomething() {
//logic for strategy 1
}
}
public class ConcreteStrategy2 implements Strategy {
@Override
public void doSomething() {
//logic for strategy 2
}
}
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void doSomething() {
strategy.doSomething();
}
}
In the above code, we have defined the strategy interface, ‘Strategy‘. Two concrete strategies, ‘ConcreteStrategy1‘ and ‘ConcreteStrategy2‘, are also defined. The ‘Context‘ class takes a strategy object in its constructor and delegates behavior to it.
To add a new strategy, all we need to do is create a new class that implements the ‘Strategy‘ interface and provides its own implementation of the behavior. The ‘Context‘ class does not need to be modified to accommodate this new strategy, as long as it conforms to the ‘Strategy‘ interface.
This approach adheres to the Open/Closed Principle because new strategies can be added without modifying existing code. It also provides flexibility and extensibility because the ‘Context‘ class can use any strategy object that conforms to the ‘Strategy‘ interface, which means that new behaviors can be added without recompiling the ‘Context‘ or other clients that use it.