Strategy Design Pattern Example and Implementation
In our previous discussion Strategy Design Pattern, we explored the Strategy Design Pattern, a powerful tool in software design. We learned what it is, its key features, and its components. We also looked at real-world examples and discussed when it’s useful and when it might not be the best choice. Now we’ll use a new example to see how this pattern works in action. By breaking down the implementation step by step, we’ll make it easier to understand how to apply this pattern effectively.
Strategy Design Pattern Example
In a transportation system, users need to travel from one location to another using different modes of transportation, such as cars, bicycles, and walking. The system should support dynamic selection and switching between these travel modes based on user preferences or travel requirements.
Challenges Without Using Strategy Pattern
- Code Duplication: Implementing different travel modes directly in the transportation system can lead to code duplication and violates the single responsibility principle.
- Tight Coupling: The transportation system may become tightly coupled with specific travel implementations, making it challenging to modify or extend the travel options.
- Lack of Flexibility: Without a clear separation of concerns, it’s difficult to dynamically switch between travel modes at runtime or add new travel options without modifying existing code.
How Strategy Pattern helps to solve the above challenges
- Encapsulation: The Strategy pattern encapsulates each travel mode into its own class, promoting code reuse and maintainability.
- Separation of Concerns: It separates the behavior (travel modes) from the context (transportation system), allowing them to vary independently.
- Flexibility: By dynamically assigning travel strategies to the transportation system, the system gains flexibility in adapting to different user preferences or travel requirements.
Complete Code of the above example
1. Define the Strategy Interface
We start by defining the “TravelStrategy"
interface, which declares a method “travel"
for traveling from one location to another.
Java
interface TravelStrategy { void travel(String source, String destination); } |
2. Implement Concrete Strategies
We then create concrete strategy classes implementing the “TravelStrategy"
interface for each travel mode: “CarTravelStrategy"
, “BicycleTravelStrategy"
, and “WalkingTravelStrategy".
Java
class CarTravelStrategy implements TravelStrategy { @Override public void travel(String source, String destination) { System.out.println( "Traveling by car from " + source + " to " + destination); } } class BicycleTravelStrategy implements TravelStrategy { @Override public void travel(String source, String destination) { System.out.println( "Traveling by bicycle from " + source + " to " + destination); } } class WalkingTravelStrategy implements TravelStrategy { @Override public void travel(String source, String destination) { System.out.println( "Traveling on foot from " + source + " to " + destination); } } |
3. Create the Context Class
We define a context class “TravelPlanner"
, which has a reference to the “TravelStrategy"
interface. This class will utilize the selected travel strategy to perform travel operations.
Java
class TravelPlanner { private TravelStrategy travelStrategy; public TravelPlanner(TravelStrategy travelStrategy) { this .travelStrategy = travelStrategy; } public void setTravelStrategy(TravelStrategy travelStrategy) { this .travelStrategy = travelStrategy; } public void planTravel(String source, String destination) { travelStrategy.travel(source, destination); } } |
4. Client Code
Finally, in the client code, we instantiate the “TravelPlanner"
object and specify the desired travel mode dynamically.
Java
public class Client { public static void main(String[] args) { TravelPlanner travelPlanner = new TravelPlanner( new CarTravelStrategy()); // Plan travel by car travelPlanner.planTravel( "Home" , "Office" ); // Change strategy to bicycle travelPlanner.setTravelStrategy( new BicycleTravelStrategy()); // Plan travel by bicycle travelPlanner.planTravel( "Office" , "Park" ); // Change strategy to walking travelPlanner.setTravelStrategy( new WalkingTravelStrategy()); // Plan travel by walking travelPlanner.planTravel( "Park" , "Restaurant" ); } } |
Complete code for the above example
Below is the complete code for the above example:
Java
// TravelStrategy.java interface TravelStrategy { void travel(String source, String destination); } // CarTravelStrategy.java class CarTravelStrategy implements TravelStrategy { @Override public void travel(String source, String destination) { System.out.println( "Traveling by car from " + source + " to " + destination); } } // BicycleTravelStrategy.java class BicycleTravelStrategy implements TravelStrategy { @Override public void travel(String source, String destination) { System.out.println( "Traveling by bicycle from " + source + " to " + destination); } } // WalkingTravelStrategy.java class WalkingTravelStrategy implements TravelStrategy { @Override public void travel(String source, String destination) { System.out.println( "Traveling on foot from " + source + " to " + destination); } } // TravelPlanner.java class TravelPlanner { private TravelStrategy travelStrategy; public TravelPlanner(TravelStrategy travelStrategy) { this .travelStrategy = travelStrategy; } public void setTravelStrategy(TravelStrategy travelStrategy) { this .travelStrategy = travelStrategy; } public void planTravel(String source, String destination) { travelStrategy.travel(source, destination); } } // Client.java public class Client { public static void main(String[] args) { TravelPlanner travelPlanner = new TravelPlanner( new CarTravelStrategy()); // Plan travel by car travelPlanner.planTravel( "Home" , "Office" ); // Change strategy to bicycle travelPlanner.setTravelStrategy( new BicycleTravelStrategy()); // Plan travel by bicycle travelPlanner.planTravel( "Office" , "Park" ); // Change strategy to walking travelPlanner.setTravelStrategy( new WalkingTravelStrategy()); // Plan travel by walking travelPlanner.planTravel( "Park" , "Restaurant" ); } } |
Output
Traveling by car from Home to Office Traveling by bicycle from Office to Park Traveling on foot from Park to Restaurant |
Conclusion
In this example, the Strategy Design Pattern allows us to dynamically select and switch between different travel modes (CarTravelStrategy
, BicycleTravelStrategy
, WalkingTravelStrategy
) without modifying the TravelPlanner
class. This provides flexibility and extensibility to the transportation system, enabling it to accommodate various travel preferences and scenarios.
Contact Us