Strategy

From CSSEMediaWiki
(Difference between revisions)
Jump to: navigation, search
m (Reverted edits by Ebybymic (Talk); changed back to last version by Mujtaba Alshakhouri)
 
(16 intermediate revisions by 9 users not shown)
Line 1: Line 1:
 +
[[Category:Design Patterns]]
 +
[[Category:Behavioural Patterns]]
 
== Intent ==
 
== Intent ==
  
Line 7: Line 9:
 
There are several reasons that this can be useful.
 
There are several reasons that this can be useful.
  
 +
* Many related classes only differ in behavior.
 
* There are several different versions of the algorithm to implement.
 
* There are several different versions of the algorithm to implement.
* The algorithms are used in more than one place. [[Once and only once]]
+
* The algorithms are used in more than one place. (See [[Once and only once]])
* There is a need to create an encapsulation boundary around the algorithm to hide implementation details.
+
* There is a need to create an encapsulation boundary around the algorithm to hide implementation details. This can for example be useful when the algorithm uses data that clients shouldn't know about.
* The class using the strategy implements many different behaviours choosing which behaviour to use with ''if'' statements. Each choice can be represented as a strategy instead simplifying code and making the intent explicit.The strategy pattern is useful for situations where
+
* The class using the strategy implements many different behaviours choosing which behaviour to use with ''if'' statements. Each choice can be represented as a strategy instead simplifying code and making the intent explicit.  
* it is necessary to dynamically swap the algorithms used in an application
+
* many related classes just differ in their behaviour
+
  
 
== UML Diagram ==
 
== UML Diagram ==
Line 18: Line 19:
  
 
== Example ==
 
== Example ==
An Example would be a tax program, where you have different methods of calculating the taxrates depending on the country.  
+
An Example would be a tax program, where you have different methods of calculating tax depending on the country. You could use a country variable and a switch to decide which algorithm to use in order to calculate the tax, but this introduces a [[Switch statement smell|switch statement smell]].  
  
== Strategy vs State ==
+
Using the strategy pattern for this problem involves encapsulating the tax calculation algorithm for each county in  a separate class. These classes all inherit the same interface so they can be used by a TaxManager to calculate tax.
 +
 
 +
[[image:StrategyExampleTax.gif|frame|centre|'''Figure 2: A UML [[Class diagram|class diagram]] applying the strategy pattern to the Tax calculation example''']]
 +
 
 +
=== Another Example ===
 +
You can find [http://java.dzone.com/articles/design-patterns-strategy here] a nicely explained java code example of the Strategy Pattern usage in the real world.
 +
 
 +
== Strategy vs State vs Bridge ==
 
The [[State]] pattern in terms of design is quite similar to the Strategy pattern, but they differ in the way they are used. While in the derived classes of the strategy pattern most of the times just one different algorithm is implemented, the derived classes of the state pattern usually represent an independent state of something. That means they have their own fields, methods and so on.
 
The [[State]] pattern in terms of design is quite similar to the Strategy pattern, but they differ in the way they are used. While in the derived classes of the strategy pattern most of the times just one different algorithm is implemented, the derived classes of the state pattern usually represent an independent state of something. That means they have their own fields, methods and so on.
 +
 +
The class diagram for the [[Bridge]] pattern is also similar to the Strategy pattern, however the intents of the patterns differ. The Strategy pattern is used to model behaviour, while the Bridge pattern is used to model structure. Additionally, in the Bridge pattern there are two layers of abstraction (for both the abstractions and the implementations), while the Strategy pattern only specifies one layer of abstraction (for the strategy).
 +
 +
== Strategy meets Template ==
 +
Strategy pattern  works well with Template method pattern. The example of such combination of patterns could be found on [[Strategy meets Template]].
  
 
== Recognising the pattern ==
 
== Recognising the pattern ==
Line 29: Line 42:
 
* multiple ConcreteStrategy classes that implement the Strategy interface.
 
* multiple ConcreteStrategy classes that implement the Strategy interface.
 
* Client class(es) that call the execute() method in Strategy interface.
 
* Client class(es) that call the execute() method in Strategy interface.
* not [[Decorator]] pattern.
+
* Not the [[Decorator]] pattern.
 +
 
 +
==Consequences==
 +
*Strategy gives you an easy way to define families of related algorithms.
 +
*Strategy gives you an alternative to subclassing Context. Subclasses can make the context hard to understand, maintain and extend. It also means that you can't vary the algorithm dynamically.
 +
*Strategy eliminates the need for lots of conditional statements used to select the desired behavior. This would be necessary if all algorithms were lumped into the same class.
 +
*Strategy gives clients a choice of implementation for the same behavior depending on the client's needs.
 +
*Clients must be aware that there are different Strategies and must understand how they work in order to select the correct one to use. Therefore, Strategy should only be used when the variations in behavior are relevant to the client.
 +
*There is a communication overhead between strategy and context because the related data and behavior have been separated.
 +
*Strategy increases the number of objects needed in an application. This can be addressed using the [[Flyweight]] pattern to share Strategy objects.
 +
 
 +
==Related Patterns==
 +
*[[Flyweight]]: Strategy objects can often be shared using the [[Flyweight]] pattern.
 +
*[[Decorator]]: Another way of changing an object by wrapping it.
 +
*[[State]]: Similar structure to Strategy, but with a different intent.
 +
*[[Bridge]]: Similar structure to Strategy, but with a different intent.
 +
*[[Command]]: Similar to Strategy in the way that specific behavior is achieved by concrete subclasses.
 +
 
 +
==Related Heuristics==
 +
*[[Favor composition over inheritance]]
 +
*[[Separation of concerns]]
 +
 
 +
==Conflicting Heuristics==
 +
*[[Keep related data and behavior in one place]]
 +
*[[Behavioral completeness]]
 +
*[[Feature envy smell|Feature envy smell]]
  
 
== See also ==
 
== See also ==
 
* [[Bridge]]
 
* [[Bridge]]
 
* [[State]]
 
* [[State]]
 +
 +
{{design patterns}}

Latest revision as of 03:22, 25 November 2010

Contents

Intent

"Define a family of algorithms, encapsulate each one, and make them interchangeable" [GoF] That means to capture the abstraction in an interface and bury implementation in derived class, so that it lets the algorithm vary independently from clients that use it depending on the context.

When to use it

The strategy pattern is useful when there is a need to separate the implementation of a process from the class that uses it. There are several reasons that this can be useful.

  • Many related classes only differ in behavior.
  • There are several different versions of the algorithm to implement.
  • The algorithms are used in more than one place. (See Once and only once)
  • There is a need to create an encapsulation boundary around the algorithm to hide implementation details. This can for example be useful when the algorithm uses data that clients shouldn't know about.
  • The class using the strategy implements many different behaviours choosing which behaviour to use with if statements. Each choice can be represented as a strategy instead simplifying code and making the intent explicit.

UML Diagram

Strategy.jpg

Example

An Example would be a tax program, where you have different methods of calculating tax depending on the country. You could use a country variable and a switch to decide which algorithm to use in order to calculate the tax, but this introduces a switch statement smell.

Using the strategy pattern for this problem involves encapsulating the tax calculation algorithm for each county in a separate class. These classes all inherit the same interface so they can be used by a TaxManager to calculate tax.

Figure 2: A UML class diagram applying the strategy pattern to the Tax calculation example

Another Example

You can find here a nicely explained java code example of the Strategy Pattern usage in the real world.

Strategy vs State vs Bridge

The State pattern in terms of design is quite similar to the Strategy pattern, but they differ in the way they are used. While in the derived classes of the strategy pattern most of the times just one different algorithm is implemented, the derived classes of the state pattern usually represent an independent state of something. That means they have their own fields, methods and so on.

The class diagram for the Bridge pattern is also similar to the Strategy pattern, however the intents of the patterns differ. The Strategy pattern is used to model behaviour, while the Bridge pattern is used to model structure. Additionally, in the Bridge pattern there are two layers of abstraction (for both the abstractions and the implementations), while the Strategy pattern only specifies one layer of abstraction (for the strategy).

Strategy meets Template

Strategy pattern works well with Template method pattern. The example of such combination of patterns could be found on Strategy meets Template.

Recognising the pattern

Classes: Strategy, multiple ConcreteStrategies, Client

  • Strategy interface that contains public abstract execute() method.
  • multiple ConcreteStrategy classes that implement the Strategy interface.
  • Client class(es) that call the execute() method in Strategy interface.
  • Not the Decorator pattern.

Consequences

  • Strategy gives you an easy way to define families of related algorithms.
  • Strategy gives you an alternative to subclassing Context. Subclasses can make the context hard to understand, maintain and extend. It also means that you can't vary the algorithm dynamically.
  • Strategy eliminates the need for lots of conditional statements used to select the desired behavior. This would be necessary if all algorithms were lumped into the same class.
  • Strategy gives clients a choice of implementation for the same behavior depending on the client's needs.
  • Clients must be aware that there are different Strategies and must understand how they work in order to select the correct one to use. Therefore, Strategy should only be used when the variations in behavior are relevant to the client.
  • There is a communication overhead between strategy and context because the related data and behavior have been separated.
  • Strategy increases the number of objects needed in an application. This can be addressed using the Flyweight pattern to share Strategy objects.

Related Patterns

  • Flyweight: Strategy objects can often be shared using the Flyweight pattern.
  • Decorator: Another way of changing an object by wrapping it.
  • State: Similar structure to Strategy, but with a different intent.
  • Bridge: Similar structure to Strategy, but with a different intent.
  • Command: Similar to Strategy in the way that specific behavior is achieved by concrete subclasses.

Related Heuristics

Conflicting Heuristics

See also


Personal tools