In
computer programming
Computer programming is the process of performing a particular computation (or more generally, accomplishing a specific computing result), usually by designing and building an executable computer program. Programming involves tasks such as anal ...
, the strategy pattern (also known as the policy pattern) is a
behavioral
Behavior (American English) or behaviour (British English) is the range of actions and mannerisms made by individuals, organisms, systems or artificial entities in some environment. These systems can include other systems or organisms as we ...
software design pattern
In software engineering, a software design pattern is a general, reusable solution to a commonly occurring problem within a given context in software design. It is not a finished design that can be transformed directly into source or machine co ...
that enables selecting an
algorithm
In mathematics and computer science, an algorithm () is a finite sequence of rigorous instructions, typically used to solve a class of specific problems or to perform a computation. Algorithms are used as specifications for performing ...
at runtime. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use.
Strategy lets the algorithm vary independently from clients that use it. Strategy is one of the patterns included in the influential book ''
Design Patterns'' by Gamma et al.
that popularized the concept of using design patterns to describe how to design flexible and reusable object-oriented software. Deferring the decision about which algorithm to use until runtime allows the calling code to be more flexible and reusable.
For instance, a class that performs validation on incoming data may use the strategy pattern to select a validation algorithm depending on the type of data, the source of the data, user choice, or other discriminating factors. These factors are not known until run-time and may require radically different validation to be performed. The validation algorithms (strategies), encapsulated separately from the validating object, may be used by other validating objects in different areas of the system (or even different systems) without
code duplication In computer programming, duplicate code is a sequence of source code that occurs more than once, either within a program or across different programs owned or maintained by the same entity. Duplicate code is generally considered undesirable for a ...
.
Typically, the strategy pattern stores a reference to some code in a data structure and retrieves it. This can be achieved by mechanisms such as the native
function pointer
A function pointer, also called a subroutine pointer or procedure pointer, is a pointer that points to a function. As opposed to referencing a data value, a function pointer points to executable code within memory. Dereferencing the function poi ...
, the
first-class function
In computer science, a programming language is said to have first-class functions if it treats functions as first-class citizens. This means the language supports passing functions as arguments to other functions, returning them as the values from ...
, classes or class instances in
object-oriented programming
Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects", which can contain data and code. The data is in the form of fields (often known as attributes or ''properties''), and the code is in the form of ...
languages, or accessing the language implementation's internal storage of code via
reflection Reflection or reflexion may refer to:
Science and technology
* Reflection (physics), a common wave phenomenon
** Specular reflection, reflection from a smooth surface
*** Mirror image, a reflection in a mirror or in water
** Signal reflection, in ...
.
Structure
UML class and sequence diagram
In the above
UML
The Unified Modeling Language (UML) is a general-purpose, developmental modeling language in the field of software engineering that is intended to provide a standard way to visualize the design of a system.
The creation of UML was originally m ...
class diagram
In software engineering, a class diagram in the Unified Modeling Language (UML) is a type of static structure diagram that describes the structure of a system by showing the system's classes, their attributes, operations (or methods), and the rela ...
, the
Context
class doesn't implement an algorithm directly.
Instead,
Context
refers to the
Strategy
interface for performing an algorithm (
strategy.algorithm()
), which makes
Context
independent of how an algorithm is implemented.
The
Strategy1
and
Strategy2
classes implement the
Strategy
interface, that is, implement (encapsulate) an algorithm.
The
UML
The Unified Modeling Language (UML) is a general-purpose, developmental modeling language in the field of software engineering that is intended to provide a standard way to visualize the design of a system.
The creation of UML was originally m ...
sequence diagram
A sequence diagram or system sequence diagram (SSD) shows process interactions arranged in time sequence in the field of software engineering. It depicts the processes involved and the sequence of messages exchanged between the processes needed ...
shows the run-time interactions: The
Context
object delegates an algorithm to different
Strategy
objects. First,
Context
calls
algorithm()
on a
Strategy1
object,
which performs the algorithm and returns the result to
Context
.
Thereafter,
Context
changes its strategy and calls
algorithm()
on a
Strategy2
object,
which performs the algorithm and returns the result to
Context
.
Class diagram
Example
C#
The following example is in
C#.
public class StrategyPatternWiki
// CustomerBill as class name since it narrowly pertains to a customer's bill
class CustomerBill
interface IBillingStrategy
// Normal billing strategy (unchanged price)
class NormalStrategy : IBillingStrategy
// Strategy for Happy hour (50% discount)
class HappyHourStrategy : IBillingStrategy
Python
The following example is equivalent to the C# example above, but in Python.
import abc
from typing import List
class Bill:
def __init__(self, billing_strategy: "BillingStrategy"):
self.drinks: list loat= []
self._billing_strategy = billing_strategy
@property
def billing_strategy(self) -> "BillingStrategy":
return self._billing_strategy
@billing_strategy.setter
def billing_strategy(self, billing_strategy: "BillingStrategy") -> None:
self._billing_strategy = billing_strategy
def add(self, price: float, quantity: int) -> None:
self.drinks.append(self.billing_strategy.get_act_price(price * quantity))
def __str__(self) -> str:
return str(f"£")
class BillingStrategy(abc.ABC):
@abc.abstractmethod
def get_act_price(self, raw_price: float) -> float:
raise NotImplementedError
class NormalStrategy(BillingStrategy):
def get_act_price(self, raw_price: float) -> float:
return raw_price
class HappyHourStrategy(BillingStrategy):
def get_act_price(self, raw_price: float) -> float:
return raw_price * 0.5
def main() -> None:
normal_strategy = NormalStrategy()
happy_hour_strategy = HappyHourStrategy()
customer_1 = Bill(normal_strategy)
customer_2 = Bill(normal_strategy)
# Normal billing
customer_1.add(2.50, 3)
customer_1.add(2.50, 2)
# Start happy hour
customer_1.billing_strategy = happy_hour_strategy
customer_2.billing_strategy = happy_hour_strategy
customer_1.add(3.40, 6)
customer_2.add(3.10, 2)
# End happy hour
customer_1.billing_strategy = normal_strategy
customer_2.billing_strategy = normal_strategy
customer_1.add(3.10, 6)
customer_2.add(3.10, 2)
# Print the bills;
print(customer_1)
print(customer_2)
if __name__ "__main__":
main()
Java
The following example is in
Java
Java (; id, Jawa, ; jv, ꦗꦮ; su, ) is one of the Greater Sunda Islands in Indonesia. It is bordered by the Indian Ocean to the south and the Java Sea to the north. With a population of 151.6 million people, Java is the world's mos ...
.
import java.util.ArrayList;
import java.util.List;
import java.util.function.IntUnaryOperator;
enum BillingStrategy
class CustomerBill
public class StrategyPattern
Strategy and open/closed principle
According to the strategy pattern, the behaviors of a class should not be inherited. Instead, they should be encapsulated using interfaces. This is compatible with the
open/closed principle (OCP), which proposes that classes should be open for extension but closed for modification.
As an example, consider a car class. Two possible functionalities for car are ''brake'' and ''accelerate''. Since accelerate and brake behaviors change frequently between models, a common approach is to implement these behaviors in subclasses. This approach has significant drawbacks: accelerate and brake behaviors must be declared in each new Car model. The work of managing these behaviors increases greatly as the number of models increases, and requires code to be duplicated across models. Additionally, it is not easy to determine the exact nature of the behavior for each model without investigating the code in each.
The strategy pattern uses
composition instead of inheritance. In the strategy pattern, behaviors are defined as separate interfaces and specific classes that implement these interfaces. This allows better decoupling between the behavior and the class that uses the behavior. The behavior can be changed without breaking the classes that use it, and the classes can switch between behaviors by changing the specific implementation used without requiring any significant code changes. Behaviors can also be changed at run-time as well as at design-time. For instance, a car object's brake behavior can be changed from
BrakeWithABS()
to
Brake()
by changing the
brakeBehavior
member to:
brakeBehavior = new Brake();
/* Encapsulated family of Algorithms
* Interface and its implementations
*/
public interface IBrakeBehavior
public class BrakeWithABS implements IBrakeBehavior
public class Brake implements IBrakeBehavior
/* Client that can use the algorithms above interchangeably */
public abstract class Car
/* Client 1 uses one algorithm (Brake) in the constructor */
public class Sedan extends Car
/* Client 2 uses another algorithm (BrakeWithABS) in the constructor */
public class SUV extends Car
/* Using the Car example */
public class CarExample
See also
*
Dependency injection
*
Higher-order function
*
List of object-oriented programming terms
This is a list of terms found in object-oriented programming. Some are related to object-oriented programming and some are not.
A
*Abstract class
*Accessibility
* Abstract method
*Abstraction (computer science)
*Access control
*Access modifier ...
*
Mixin
In object-oriented programming languages, a mixin (or mix-in) is a class that contains methods for use by other classes without having to be the parent class of those other classes. How those other classes gain access to the mixin's methods depen ...
*
Policy-based design
''Modern C++ Design: Generic Programming and Design Patterns Applied'' is a book written by Andrei Alexandrescu, published in 2001 by Addison-Wesley. It has been regarded as "one of the most important C++ books" by Scott Meyers.
The book makes u ...
*
Type class
*
Entity–component–system
Entity Component System (ECS) is a software architectural pattern mostly used in video game development for the representation of game world objects. An ECS comprises ''entities'' composed from ''components'' of data, with ''systems'' which opera ...
*
Composition over inheritance
Composition over inheritance (or composite reuse principle) in object-oriented programming (OOP) is the principle that classes should achieve polymorphic behavior and code reuse by their composition (by containing instances of other classes tha ...
References
External links
Strategy Pattern in UML
*
Strategy Pattern for C article* Implementation of the Strategy pattern in JavaScript
{{Design Patterns Patterns
Software design patterns
Articles with example C Sharp code
Articles with example Java code