Concrete Strategies: The classes that implement the Strategy Interface with different variations of an algorithm the context uses.. Solution: We need to design a system that separates a
Trang 1TRƯỜNG ĐẠI HỌC KHOA HỌC TỰ NHIÊN TP.HCM
KHOA CÔNG NGHỆ THÔNG TIN
Mẫu thiết kế hướng đối tượng và ứng dụng
STRATEGY DESIGN PATTERN
Giáo viên: Nguyễn Minh Huy
Ngô Ngọc Đăng Khoa
Trương Toàn Thịnh
Trang 2Mục lục
1 Brief Description: Strategy design pattern 3
2 Problems/ motivation 4
3 Solution, class diagram and explanation: 4
3.1 Solution: 4
3.2 Class diagram: 5
3.3 Explanation: 5
4 Specific problem, class diagram and explanation: 5
4.1 Problem Description: 5
4.2 Solution: 6
5 Sample code and explanation 9
5.1 Example with code not using Strategy Design Pattern: 9
5.2 Example with code using Strategy Design Pattern: 10
6 Advantages and disadvantages 14
6.1 Advantages 14
6.3 Disadvantages 14
7 Comparing Strategy & State 14
Group’s Information
Student’s ID Name
20127100 Nguyễn Trịnh Như Ý
20127343 Phạm Ngọc Anh Thư
20127575 Huỳnh Cao Nguyên
Trang 31 Brief Description: Strategy design pattern
Strategy is a behavioral software design pattern Strategy helps change or select an algorithm at
runtime It is one of the Gang of Four design patterns and is widely used in object-oriented
programming Strategy is also known as Policy Pattern
Gangs of Four Design Patterns is the collection of 23 design patterns from the book “Design
Patterns: Elements of Reusable Object-Oriented Software”
This book was first published in 1994 and it’s one of the most popular books to learn design
patterns The book was authored by Erich Gamma, Richard Helm, Ralph Johnson, and John
Vlissides It got nicknamed as Gangs of Four design patterns because of four authors Furthermore,
it got a shorter name as “GoF Design Patterns”
Strategy pattern is used when we have multiple algorithms for a specific task and the client decides
which one is going to be used at runtime Some popular problems that are used for introducing
strategy pattern:
- SimUDuck app with many types of ducks but different behaviors
- Route finding but users could be walking or riding different vehicles
- Calculator which performs many kinds of calculations
It is designed based on this design principle: “Identify the aspects of your application that vary and
separate them from what stays the same.”
Another way to think about it is what part is different and varies from classes when passing down in
inheritance, take it out and encapsulate them So later you can change or add more to it without
affecting the old code
In strategy design pattern case, it is the methods, algorithms that change and vary in different
classes
With this design, other types of objects can reuse the behaviors because these behaviors are not
hidden in classes that inherit the abstract class We can also add new behaviors without changing
code that existed before This design also helps the maintaining progress to be much easier when all
the algorithms of the same group stay in one place
Definition in Head First Design Patterns, Oreilly: “The Strategy Pattern defines a family of
algorithms, encapsulates each one, and makes them interchangeable Strategy lets the
algorithm vary independently from clients that use it.”
Trang 42 Problems/ motivation
There are many algorithms that are somewhat solving one problem but with different purposes
based on who the customer is and what they want (Example: finding route for motorbikes/ cars,
calculating but add is different from substract)
- If we just design a program that can just solve one problem with one purpose and one way
only, it will be hard to update if customers need new things to solve their problems
- If we take all of these methods into one class, it will become a GOD class, which is hard to
maintain or fix bugs
There are also objects that have all the same behaviors, but behave inside the behaviors a little bit
differently (Etc: different types of dogs do not look the same or behaves, but you can tell they are
dogs based on similarities in behaviors, appearance) If using if/else statements or switch case for
this kind of problem, it will make code long and hard to maintain and could possibly miss out a few
conditions results in bug or redundant
In addition, this can cause trouble for teamwork as well Implementing a new feature or updating a
previous feature requires changing the same huge class, because all the methods stay in one place
3 Solution, class diagram and explanation:
3.1 Solution:
The Strategy Design Pattern works by separating the behavior of an object from the object itself
The behavior is encapsulated into different strategies, each with its own implementation of the
behavior
The context maintains a reference to a strategy object and interacts with it through a common
interface At runtime, the context can swap the current strategy with another one, effectively
changing the object's behavior
Trang 53.2 Class diagram:
3.3 Explanation:
The Context:The object that will delegate its behavior to one of the contained strategies The
context maintains a reference to one of the concrete strategies (strategy object) and communicates
with this object only via the strategy interface that lets strategy access its data
The Strategy interface: The interface that defines the behavior for all supported algorithms The
strategies implement this interface to provide their unique implementation of the behavior Context
uses this interface to call the algorithm defined by Concrete Strategies
Concrete Strategies: The classes that implement the Strategy Interface with different variations of
an algorithm the context uses Each class encapsulates a specific behavior that the context can
switch to at runtime
The Client creates a specific strategy object and passes it to the context The context exposes a
setter which lets clients replace the strategy associated with the context at runtime
4 Specific problem, class diagram and explanation:
4.1 Problem Description:
We need to design a game that can show a large variety of duck species flying and making quacking
sounds
In casual, developers will think about inheritance to avoid duplicated code and creating a new from
scratch if there is no similarity in the feature of prior work But at some point, the code will be twice
as prior work or be dependent on each other Any change to one of the algorithms, whether it was a
Trang 6simple bug fix or a slight adjustment of the street score, affected the whole class, increasing the
chance of creating an error in already-working code
4.2 Solution:
We need to design a system that separates a class Duck and its behavior method implements (extract
all of duck behavior into separate classes)
Firstly, we identify behavior that’s prone to frequent changes For example, in the duck’s flying
behavior, we have some ducks that can fly with their wings while some others can not fly In the
duck’s quacking behavior, we have some ducks' sound like quack quack, some ducks’s sound like
“Squeak Squeak” and the rubber ducks cannot quack
We separate the fly behavior and quack behavior of duck into FlyBehavior and QuackBehavior
interface and they have their method is fly() which will execute how duck fly and quack() method
which will execute how duck quack
With those interfaces, one by one, we implement the way that ducks fly and quack into their own
classes
Trang 7And create a duck abstract class that delegates its fly and quack behavior to their references, instead
of using quacking and flying methods defined in the Duck class (or subclass)
Duck (Context)
- This class has 2 private attributes flyBehavior and quackBehavior that store a reference to the
Concrete Strategies and communicates with this object only via the strategy
interface(QuackBehavior and FlyBehavior) Those 2 fields can be replaced, making them
Trang 8interchangeable with different ways of behavior to change how it executes their behavior in
run-time
- The method performFly() and performQuack() will execute the behavior that field
flyBehavior and quackBehavior stored, run the method fly() and quack() implemented in
Concrete Strategies
- Clients can change a duck behavior with specific flyBehavior and quackBehavior thorough
method setters
Strategy (FlyBehavior & QuackBehavior):
- Those interfaces define a set of methods that all Concrete Strategies classes must implement,
which will be called by Duck method
Concrete Strategies(FlyWithWings, NoFly, Quack):
- Those classes are the implements for FlyBehavior & QuackBehavior (Strategies)
- FlyWithWings implements FlyBehavior with method fly defines the way that ducks fly with
their wings
- NoFly implements FlyBehavior with method fly defines that the duck cannot fly
- Quack implements QuackBehavior with method quack defines the sound that ducks make
Usage:
There is 2 way to create a type of duck:
● Make an inheritance of Duck:
For instance, create a new class call “MallardDuck” that ỉneritance of Duck and with
assigning initial setup of specific behaviors for that duck like FlyWithWings and Quack
behavior
● Create a new Duck and set its behavior:
For instance, create an object with Duck datatype name “mallardDuck” and set the
behavior for that Duck object by method setFlyBehavior and setQuackBehvior
Trang 95 Sample code and explanation
5.1 Example with code not using Strategy Design Pattern:
Trang 10This code I provide here implements the game that can show a large variety of duck species flying
and making quacking sounds without using the strategy design pattern
Benefit:
Without implementing the Strategy pattern, the code is relatively simple and straightforward There
are fewer abstractions and design patterns, making it easier for beginners to understand And there is
less abstraction, which can lead to more direct control over the code and may be suitable for small,
non-complex projects
Drawbacks:
Behaviors are tightly coupled with the context class This can lead to code duplication if similar
behaviors need to be reused in other parts of the program And changing behaviors at runtime or
accommodating new behaviors becomes challenging Furthermore, testing can be more complex
because behaviors are not encapsulated in separate classes It can be harder to isolate and test
specific behaviors
5.2 Example with code using Strategy Design Pattern:
Duck:
Trang 11- Method setFlyBehavior(FlyBehavior fly), setQuackBehavior(QuackBehavior quack) change
the initial behavior of an object and can be used at run-time to perform another variant
behavior
- The context method performQuack(), performFly() delegates the work to linked strategy
objects instead of executing it on its own
FlyBehavior:
- Fly is a common feature of Duck Interface FlyBehavior defines a method that the context
Duck will use to illustrate how ducks fly
QuackBehavior:
- Quack is a common feature of Duck Interface QuackBehavior defines a method that the
context Duck will use to illustrate how ducks quack
FlyWithWings:
- FlyWithWings implements FlyBehavior as it is a specific variation of duck’s fly behavior that
some kinds of ducks can do
Trang 12- NoFly implements FlyBehavior as it is a specific variation of duck’s fly behavior that some
kinds of ducks can not fly
Quack:
- Quack implements QuackBehavior as it is a specific variation of duck’s quack behavior that
some kinds of ducks sound quack quack
MallardDuck:
Trang 13ModelDuck :
- ModelDuck is an inheritance of Duck When a ModelDuck is instantiated, its constructor
initializes the ModelDuck inherited quackBehavior instance variable to a new instance of
type Quack (a QuackBehavior concrete implementation class)
- And the same is true for the duck’s flying behavior- the ModelDuck’s constructor initializes
the flyBehavior instance variable with an instance of type NoFly (a FlyBehavior concrete
implementation class)
Client:
- This class Client will use the game system, by calling the Duck type, making them perform
their features like fly and quack
Trang 14- A duck object’s behavior can be changed at runtime, clients just need to call the duck object’s
setter method for that behavior
6 Advantages and disadvantages
6.1 Advantages
- Reduce code duplication, prevent GOD class, swap algorithms during runtime
- Follows the open/closed principle of object-oriented design, making it easier to add new
strategies or modify existing ones without affecting the context class or other strategies
- Follows the Single Responsibility Principle by encapsulating different strategies into separate
classes
6.2 Disadvantages
- In simple scenarios, the Strategy Pattern might introduce unnecessary complexity It can be
overkill for systems with only a few fixed algorithms
- Increased number of classes, which is bad for small scale projects and are hard to keep up
with a large hierarchy of strategies It makes code complexity increase
- Clients must know what they want for using which methods to help them solve their problem
7 Comparing Strategy & State
State and Strategy are considered to look alike by many people What’s the difference between
them? Why can’t we use Strategy for states too?
- Strategy concentrates on behaviors, methods, if it's different, encapsulate it While state
focuses more in different states, and if just use only states, the different methods will not be
separated into classes
- Strategy does not encourage objects to have a defined set of state transitions It controls what
strategy its objects are using
- On the other hand, states allow switching class to class, and alter the object’s behaviors when
internal state changes That is why the state stores a reference to the context object that
contains it and strategy does not
In conclusion, strategies are having a different implementation that accomplishes (basically) the
same thingso that one implementation can replace the other as the strategy requires, while state
pattern is about doing different things based on the state of an object