Defines a family of interchangeable algorithms and encapsulates each one individually. Strategy lets the algorithm vary independently from clients that use it.
- Different strategies can be swapped as needed.
- Good for encapsulating many behaviors or algorithms that use data structures that a client shouldn't know about.
- Eliminates use of conditional statements to select the right behavior.
Unlike Template, which uses inheritance to vary parts of an algorithm, Strategy uses delegation and composition to exchange entire algorithms that are capable of being swapped dynamically in context. The actual algorithm is implemented via a context object that can be configured at run-time. The context object isolates client classes from specific dependencies on the algorithm interface by providing them with a more generic interface. An important aspect of the design of a Strategy pattern and its context object is to ensure that 1) any member of the family of related algorithms can be accommodated 2) subsequent concrete implementations, changes or additions can be adopted without modifying the interface.
Strategies allow you to make flatter class hierarchies, which are easier to manage and maintain. Class hierarchies that rely heavily on inheritance can get very deep (multiple levels) and are harder to maintain.
Structure of Strategy Pattern

Implementation of Strategy Pattern
In this sample (uStrategy.pas) monthly credit charges are computed for a hypothetical credit card. The strategy pattern allows the different family of algorithms used to compute monthly finance charges to be encapsulated and accessed uniformly through the interface of TFinanzeCharge abstract class. TRegularCharge and TPreferredCharge are concrete classes that encapsulate the different algorithms for computing monthly credit finance charges.
TMonthlyCharge implements the TContextCharge interface and is configured with the different concrete strategy objects. TContextCharge acts as a mediator between the client object and the strategy classes, helping to decouple dependencies between the client object and specific strategy/algorithm implementations.
// strategy interface (abstract class)
TFinanzeCharge = class
public
// returns monthly finance charge
function getCharge(const Balance: double): double; virtual; abstract;
end;
// Concrete Strategy 1
TRegularCharge = class(TFinanzeCharge)
public
function getCharge(const Balance: double): double; override;
end;
// Concrete Strategy 2
TPreferredCharge = class(TFinanzeCharge)
public
function getCharge(const Balance: double): double; override;
end;
The context interface is what clients will depend on when using specific strategies. Because the context is configured by the client, the client needs to be aware of the strategies/algorithms available. An alternative implementation could provide a default strategy if the context does not receive a valid instance during initialization.
// Context Interface
TChargeContext = class
public
function ComputeCharges(const Balance: double): double; virtual; abstract;
end;
// Concrete Context 1
This class acts as a mediator between the client and the strategy classes, and is configured by using composition and passing an instance of a concrete finance charge in its constructor.
TMonthlyCharges = class(TChargeContext)
private
FFinanzeCharge: TFinanzeCharge;
public
// context interface called by client classes
function ComputeCharges(const Balance: double): double; override;
// constructor configures the context object
constructor Create(aFinanzeCharge: TFinanzeCharge); virtual;
destructor Destroy; override;
end;
implementation
// TRegularCharge
function TRegularCharge.getCharge(const Balance: double): double;
begin
result := Balance * (REG_RATE / 12);
end;
// TPreferredCharge
function TPreferredCharge.getCharge(const Balance: double): double;
begin
// this could be a complex algorithm that takes into account the
// credit card holder's buying patterns and reward points accumulated.
result := Balance * (PREFERRED_RATE / 12);
end;
// Concrete Context 2
// TMonthlyCharges
constructorTMonthlyCharges.Create(aFinanzeCharge: TFinanzeCharge);
begin
inherited Create;
// aFinanzeCharge configures the context object
// this class takes ownership of aFinanzeCharge (will destroy it)
FFinanzeCharge := aFinanzeCharge;
end;
destructor TMonthlyCharges.Destroy;
begin
FFinanzeCharge.Free;
inherited Destroy;
end;
function TMonthlyCharges.ComputeCharges(const Balance: double): double;
begin
result := FFinanzeCharge.getCharge(Balance);
end;