Strategy pattern

From Wikipedia, the free encyclopedia
Jump to: navigation, search
Strategy Pattern in UML
Strategy pattern in LePUS3 (legend)

In computer programming, the strategy pattern (also known as the policy pattern) is a particular software design pattern, whereby algorithms can be selected at runtime.

The strategy pattern is useful for situations where it is necessary to dynamically swap the algorithms used in an application. The strategy pattern is intended to provide a means to define a family of algorithms, encapsulate each one as an object, and make them interchangeable. The strategy pattern lets the algorithms vary independently from clients that use them.

For instance, a class that performs validation on incoming data may use a strategy pattern to select a validation algorithm based on the type of data, the source of the data, or other discriminating factors. These factors are not known for each case until run-time, and may require radically different validation to be performed. The validation 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.

The essential requirement in the programming language is the ability to store a reference to some code in a data structure and retrieve it. This can be achieved by mechanisms such as the native function pointer, the first-class function, classes or class instances in object oriented programming languages, or accessing the language implementation's internal storage of code via reflection.

Contents

[edit] Code Examples

[edit] Ruby

class Context
  def initialize(strategy)
    self.class.send :include, strategy
  end
end
 
module StrategyA
  def execute
     puts 'Doing the task the normal way'
  end
end
 
module StrategyB
  def execute
     puts 'Doing the task alternatively'
  end
end
 
module StrategyC
  def execute
     puts 'Doing the task even more alternatively'
  end
end
 
a = Context.new(StrategyA)
a.execute #=> Doing the task the normal way
 
b = Context.new(StrategyB)
b.execute #=> Doing the task alternatively
 
c = Context.new(StrategyC)
c.execute #=> Doing the task even more alternatively

[edit] Ruby using blocks

The previous ruby example uses typical OO features, but the same effect can be accomplished with ruby's blocks in much less code.

class Context
  def initialize(&strategy)
    @strategy = strategy
  end
 
  def execute
    @strategy.call
  end
end
 
a = Context.new { puts 'Doing the task the normal way' }
a.execute #=> Doing the task the normal way
 
b = Context.new { puts 'Doing the task alternatively' }
b.execute #=> Doing the task alternatively
 
c = Context.new { puts 'Doing the task even more alternatively' }
c.execute #=> Doing the task even more alternatively

[edit] C++

#include <iostream>
using namespace std;
 
class StrategyInterface
{
    public:
        virtual void execute() const = 0;
};
 
class ConcreteStrategyA: public StrategyInterface
{
    public:
        virtual void execute() const
        {
            cout << "Called ConcreteStrategyA execute method" << endl;
        }
};
 
class ConcreteStrategyB: public StrategyInterface
{
    public:
        virtual void execute() const
        {
            cout << "Called ConcreteStrategyB execute method" << endl;
        }
};
 
class ConcreteStrategyC: public StrategyInterface
{
    public:
        virtual void execute() const
        {
            cout << "Called ConcreteStrategyC execute method" << endl;
        }
};
 
class Context
{
    private:
        StrategyInterface * strategy_;
 
    public:
        explicit Context(StrategyInterface *strategy):strategy_(strategy)
        {
        }
 
        void set_strategy(StrategyInterface *strategy)
        {
            strategy_ = strategy;
        }
 
        void execute() const
        {
            strategy_->execute();
        }
};
 
int main(int argc, char *argv[])
{
    ConcreteStrategyA concreteStrategyA;
    ConcreteStrategyB concreteStrategyB;
    ConcreteStrategyC concreteStrategyC;
 
    Context contextA(&concreteStrategyA);
    Context contextB(&concreteStrategyB);
    Context contextC(&concreteStrategyC);
 
    contextA.execute(); // output: "Called ConcreteStrategyA execute method"
    contextB.execute(); // output: "Called ConcreteStrategyB execute method"
    contextC.execute(); // output: "Called ConcreteStrategyC execute method"
 
    contextA.set_strategy(&concreteStrategyB);
    contextA.execute(); // output: "Called ConcreteStrategyB execute method"
    contextA.set_strategy(&concreteStrategyC);
    contextA.execute(); // output: "Called ConcreteStrategyC execute method"
 
    return 0;
}

[edit] Common Lisp

Using strategy classes:

(defclass context ()
  ((strategy :initarg :strategy :accessor strategy)))
 
(defmethod execute ((c context))
  (execute (slot-value c 'strategy)))
 
(defclass strategy-a () ())
 
(defmethod execute ((s strategy-a))
  (print "Doing the task the normal way"))
 
(defclass strategy-b () ())
 
(defmethod execute ((s strategy-b))
  (print "Doing the task alternatively"))
 
(execute (make-instance 'context
                        :strategy (make-instance 'strategy-a)))

In Common Lisp using first class functions:

(defclass context ()
  ((strategy :initarg :strategy :accessor strategy)))
 
(defmethod execute ((c context))
  (funcall (slot-value c 'strategy)))
 
(let ((a (make-instance 'context
                        :strategy (lambda ()
                                    (print "Doing the task the normal way")))))
  (execute a)) 
 
(let ((b (make-instance 'context
                        :strategy (lambda ()
                                    (print "Doing the task alternatively")))))
  (execute b))

[edit] Java

//StrategyExample test application
 
class StrategyExample {
 
    public static void main(String[] args) {
 
        Context context;
 
        // Three contexts following different strategies
        context = new Context(new ConcreteStrategyAdd());
        int resultA = context.executeStrategy(3,4);
 
        context = new Context(new ConcreteStrategySubtract());
        int resultB = context.executeStrategy(3,4);
 
        context = new Context(new ConcreteStrategyMultiply());
        int resultC = context.executeStrategy(3,4);
 
    }
 
}
 
// The classes that implement a concrete strategy should implement this
 
// The context class uses this to call the concrete strategy
interface Strategy {
 
    int execute(int a, int b);
 
}
 
// Implements the algorithm using the strategy interface
class ConcreteStrategyAdd implements Strategy {
 
    public int execute(int a, int b) {
        System.out.println("Called ConcreteStrategyAdd's execute()");
        return a + b;  // Do an addition with a and b
    }
 
}
 
class ConcreteStrategySubtract implements Strategy {
 
    public int execute(int a, int b) {
        System.out.println("Called ConcreteStrategySubtract's execute()");
        return a - b;  // Do a subtraction with a and b
    }
 
}
 
class ConcreteStrategyMultiply implements Strategy {
 
    public int execute(int a, int b) {
        System.out.println("Called ConcreteStrategyMultiply's execute()");
        return a * b;   // Do a multiplication with a and b
    }
 
}
 
// Configured with a ConcreteStrategy object and maintains a reference to a Strategy object
class Context {
 
    private Strategy strategy;
 
    // Constructor
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }
 
    public int executeStrategy(int a, int b) {
        return strategy.execute(a, b);
    }
 
}

[edit] Groovy

This Groovy example is a basic port of the Ruby using blocks example. In place of Ruby's blocks, the example uses Groovy's closure support.

class Context {
  def strategy
 
  Context(strategy) {
    this.strategy = strategy
  }
 
  def execute() {
    strategy()
  }
}
 
def a = new Context({ println 'Style A' })
a.execute() // => Style A
def b = new Context({ println 'Style B' })
b.execute() // => Style B
def c = new Context({ println 'Style C' })
c.execute() // => Style C

[edit] Python

Python has first-class functions, so the pattern can be used simply by passing the function directly to the context instead of defining a class with a method containing the function. One loses information because the interface of the strategy is not made explicit, however, by simplifying the pattern in this manner.

Here's an example you might encounter in GUI programming, using a callback function:

class Button:
    """A very basic button widget."""
    def __init__(self, submit_func, label):
        self.on_submit = submit_func   # Set the strategy function directly
        self.label = label
 
# Create two instances with different strategies
button1 = Button(sum, "Add 'em")
button2 = Button(lambda nums: " ".join(map(str, nums)), "Join 'em")
 
# Test each button
numbers = range(1, 10)   # A list of numbers 1 through 9
print button1.on_submit(numbers)   # displays "45"
print button2.on_submit(numbers)   # displays "1 2 3 4 5 6 7 8 9"

[edit] Scala

Like Python, Scala also supports first-class functions. The following implements the basic functionality shown in the Python example.

  // A very basic button widget.
  class Button[T](val label: String, val onSubmit: Range => T)
 
  val button1 = new Button("Add", _ reduceLeft (_ + _))
  val button2 = new Button("Join", _ mkString " ")
 
  // Test each button
  val numbers = 1 to 9  // A list of numbers 1 through 9
  println(button1 onSubmit numbers) // displays 45
  println(button2 onSubmit numbers) // displays 1 2 3 4 5 6 7 8 9

[edit] Falcon

Similar to Python and Scala, Falcon supports first-class functions. The following implements the basic functionality seen in the Python example.

 /*#
   @brief A very basic button widget
 */
 class Button( label, submit_func )
   label = label
   on_submit = submit_func
 end
 
 // Create two instances with different strategies ...
 // ... and different ways to express inline functions
 button1 = Button( "Add 'em", 
     function(nums)
        n = 0
        for val in nums: n+= val
        return n
      end )
 button2 = Button( "Join 'em", { nums => " ".merge( [].comp(nums) ) } )
 
 // Test each button
 numbers = [1: 10]  
 printl(button1.on_submit(numbers))   // displays "45"
 printl(button2.on_submit(numbers))   // displays "1 2 3 4 5 6 7 8 9"

[edit] JavaScript

Similar to Python and Scala, Javascript supports first-class functions. The following implements the basic functionality seen in the Python example.

var Button = function(submit_func, label) {
	this.label = label; 
	this.on_submit = function(numbers) { 
		return submit_func(numbers);
	};
};
 
var numbers = [1,2,3,4,5,6,7,8,9];
var sum = function(n) { 
	var sum = 0; 
	for ( var a in n ) { 
		sum = sum + n[a]; 
	} 
	return sum;
}; 
 
var a = new Button(sum, "Add numbers");
var b = new Button(function(numbers) { 
	return numbers.join(','); 
}, "Print numbers");
 
a.on_submit(numbers);
b.on_submit(numbers);

[edit] C

A struct in C can be used to define a class, and the strategy can be set using a function pointer. The following mirrors the Python example, and uses C99 features:

#include <stdio.h>
 
void print_sum(int n, int *array) {
    int total = 0;
    for (int i = 0; i < n; i++)
        total += array[i];
    printf("%d", total);
}
 
void print_array(int n, int *array) {
    for (int i = 0; i < n; i++)
        printf("%d ", array[i]);
}
 
typedef struct {
    void (*submit_func)(int n, int *array);  // function pointer
    char *label;                             // instance label
} Button;
 
int main(void) {
    // Create two instances with different strategies
    Button button1 = { print_sum, "Add 'em" };
    Button button2 = { print_array, "List 'em" };
 
    int n = 10;
    int numbers[n];
    for (int i = 0; i < n; i++)
        numbers[i] = i;
 
    button1.submit_func(n, numbers);
    button2.submit_func(n, numbers);
 
    return 0;
}

[edit] C#

Delegates in C# follow the strategy pattern, where the delegate definition defines the strategy interface and the delegate instance represents the concrete strategy. .NET 3.5 defines the Func<,> delegate which can be used to quickly implement the strategy pattern as shown in the example below. Note the 3 different methods for defining a delegate instance.

using System;
using System.Linq;
class Program
{
    static void Main(string[] args)
    {
        var context = new Context<int>();
 
        // Delegate
        Func<int, int, int> concreteStrategy1 = PerformLogicalBitwiseOr;
 
        // Anonymous Delegate
        Func<int, int, int> concreteStrategy2 = delegate(int op1, int op2) { return op1 & op2; };
 
        // Lambda Expressions
        Func<int, int, int> concreteStrategy3 = (op1, op2) => op1 >> op2;
        Func<int, int, int> concreteStrategy4 = (op1, op2) => op1 << op2;
 
        context.Strategy = concreteStrategy1;
        var result1 = context.Execute(8, 9);
        context.Strategy = concreteStrategy2;
        var result2 = context.Execute(8, 9);
        context.Strategy = concreteStrategy3;
        var result3 = context.Execute(8, 1);
        context.Strategy = concreteStrategy4;
        var result4 = context.Execute(8, 1);
    }
 
    static int PerformLogicalBitwiseOr(int op1, int op2)
    {
        return op1 | op2;
    }
 
    class Context<T>
    {
        public Func<T, T, T> Strategy { get; set; }
 
        public T Execute(T operand1, T operand2)
        {
            return this.Strategy != null
                ? this.Strategy(operand1, operand2)
                : default(T);
        }
    }
}

[edit] C# using interfaces

using System;
 
namespace Wikipedia.Patterns.Strategy
{
  // MainApp test application
  class MainApp
  {
    static void Main()
    {
      Context anObject;
 
      // Three contexts following different strategies
      anObject= new Context(new ConcreteStrategyA());
      anObject.Execute();
 
      anObject.UpdateContext(new ConcreteStrategyB());
      anObject.Execute();
 
      anObject.UpdateContext(new ConcreteStrategyC());
      anObject.Execute();
 
    }
  }
 
  // The classes that implement a concrete strategy must implement this Execute function.
  // The context class uses this to call the concrete strategy
  interface IStrategy
  {
    void Execute();
  }
 
  // Implements the algorithm using the strategy interface
  class ConcreteStrategyA : IStrategy
  {
    public void Execute()
    {
      Console.WriteLine( "Called ConcreteStrategyA.Execute()" );
    }
  }
 
  class ConcreteStrategyB : IStrategy
  {
    public void Execute()
    {
      Console.WriteLine( "Called ConcreteStrategyB.Execute()" );
    }
  }
 
  class ConcreteStrategyC : IStrategy
  {
    public void Execute()
    {
      Console.WriteLine( "Called ConcreteStrategyC.Execute()" );
    }
  }
 
  // Configured with a ConcreteStrategy object and maintains a reference to a Strategy object
  class Context
  {
    IStrategy strategy;
 
    // Constructor
    public Context(IStrategy strategy)
    {
      this.strategy = strategy;
    }
 
    public void UpdateContext(IStrategy strategy)
    {
      this.strategy = strategy;
    }
 
    public void Execute()
    {
      strategy.Execute();
    }
  }
}

[edit] ActionScript 3

//invoked from application.initialize
private function init() : void
{
    var context:Context;
 
    context = new Context( new ConcreteStrategyA() );
    context.execute();
 
    context = new Context( new ConcreteStrategyB() );
    context.execute();
 
    context = new Context( new ConcreteStrategyC() );
    context.execute();
}
 
package org.wikipedia.patterns.strategy
{
    public interface IStrategy
    {
	function execute() : void ;
    }
}
 
package org.wikipedia.patterns.strategy
{
    public final class ConcreteStrategyA implements IStrategy
    {
	public function execute():void
	{
	     trace( "ConcreteStrategyA.execute(); invoked" );
	}
    }
}
 
package org.wikipedia.patterns.strategy
{
    public final class ConcreteStrategyB implements IStrategy
    {
	public function execute():void
	{
	     trace( "ConcreteStrategyB.execute(); invoked" );
	}
    }
}
 
package org.wikipedia.patterns.strategy
{
    public final class ConcreteStrategyC implements IStrategy
    {
	public function execute():void
	{
	     trace( "ConcreteStrategyC.execute(); invoked" );
	}
    }
}
 
package org.wikipedia.patterns.strategy
{
   public class Context
   {
	private var strategy:IStrategy;
 
	public function Context(strategy:IStrategy)
	{
	     this.strategy = strategy;
	}
 
	public function execute() : void
	{  
             strategy.execute();
	}
    }
}

[edit] PHP

<?php
class StrategyExample {
    public function __construct() {
        $context = new Context(new ConcreteStrategyA());
        $context->execute();
 
        $context = new Context(new ConcreteStrategyB());
        $context->execute();
 
        $context = new Context(new ConcreteStrategyC());
        $context->execute();
    }
}
 
interface IStrategy {
    public function execute();
}
 
class ConcreteStrategyA implements IStrategy {
    public function execute() {
        echo "Called ConcreteStrategyA execute method\n";
    }
}
 
class ConcreteStrategyB implements IStrategy {
    public function execute() {
        echo "Called ConcreteStrategyB execute method\n";
    }
}
 
class ConcreteStrategyC implements IStrategy {
    public function execute() {
        echo "Called ConcreteStrategyC execute method\n";
    }
}
 
class Context {
    private $strategy;
 
    public function __construct(IStrategy $strategy) {
        $this->strategy = $strategy;
    }
 
    public function execute() {
        $this->strategy->execute();
    }
}
 
new StrategyExample();
?>

[edit] Perl

Perl has first-class functions, so as with Python, JavaScript and Scala, this pattern can be implemented without defining explicit subclasses and interfaces:

sort { lc($a) cmp lc($b) } @items

The strategy pattern can be formally implemented with Moose:

package Strategy;
use Moose::Role;
requires 'execute';
 
 
package FirstStrategy;
use Moose;
with 'Strategy';
 
sub execute {
    print "Called FirstStrategy->execute()\n";
}
 
 
package SecondStrategy;
use Moose;
with 'Strategy';
 
sub execute {
    print "Called SecondStrategy->execute()\n";
}
 
 
package ThirdStrategy;
use Moose;
with 'Strategy';
 
sub execute {
    print "Called ThirdStrategy->execute()\n";
}
 
 
package Context;
use Moose;
 
has 'strategy' => (
    is => 'rw',
    does => 'Strategy',
    handles => [ 'execute' ],  # automatic delegation
);
 
 
package StrategyExample;
use Moose;
 
# Moose's constructor
sub BUILD {
    my $context;
 
    $context = Context->new(strategy => 'FirstStrategy');
    $context->execute;
 
    $context = Context->new(strategy => 'SecondStrategy');
    $context->execute;
 
    $context = Context->new(strategy => 'ThirdStrategy');
    $context->execute;
}
 
 
package main;
 
StrategyExample->new;

[edit] Fortran

Fortran 2003 adds procedure pointers, abstract interfaces and also first-class functions. The following mirrors the Python example.

module m_strategy_pattern
implicit none
 
abstract interface
    !! A generic interface to a subroutine accepting array of integers
    subroutine generic_function(numbers)
        integer, dimension(:), intent(in) :: numbers
    end subroutine
end interface
 
type :: Button
    character(len=20) :: label
    procedure(generic_function), pointer, nopass :: on_submit
contains
    procedure :: init
end type Button
 
contains
 
    subroutine init(self, func, label)
        class(Button), intent(inout) :: self
        procedure(generic_function) :: func
        character(len=*) :: label
        self%on_submit => func      !! Procedure pointer
        self%label = label
    end subroutine init
 
    subroutine summation(array)
        integer, dimension(:), intent(in) :: array
        integer :: total
        total = sum(array)
        write(*,*) total
    end subroutine summation
 
    subroutine join(array)
        integer, dimension(:), intent(in) :: array
        write(*,*) array        !! Just write out the whole array
    end subroutine join
 
end module m_strategy_pattern
 
!! The following program demonstrates the usage of the module
program test_strategy
use m_strategy_pattern
implicit none
 
    type(Button) :: button1, button2
    integer :: i
 
    call button1%init(summation, "Add them")
    call button2%init(join, "Join them")
 
    call button1%on_submit([(i, i=1,10)])   !! Displays 55
    call button2%on_submit([(i, i=1,10)])   !! Prints out the array
 
end program test_strategy

[edit] PowerShell

PowerShell has first-class functions called ScriptBlocks, so the pattern can be modeled like Python, passing the function directly to the context instead of defining a class.

Function Context ([scriptblock]$script:strategy){
    New-Module -Name Context -AsCustomObject {
        Function Execute { & $strategy }
    }
}
 
$a = Context {'Style A'}
$a.Execute()
 
(Context {'Style B'}).Execute()
 
$c = Context {'Style C'}
$c.Execute()

An alternative to using New-Module

Function Context ([scriptblock]$strategy){
    { & $strategy }.GetNewClosure()
}
 
$a = Context {'Style A'}
$a.Invoke()
 
& (Context {'Style B'})
 
$c = Context {'Style C'}
& $c

[edit] Strategy versus Bridge

The UML class diagram for the Strategy pattern is the same as the diagram for the Bridge pattern. However, these two design patterns aren't the same in their intent. While the Strategy pattern is meant for behavior, the Bridge pattern is meant for structure.

The coupling between the context and the strategies is tighter than the coupling between the abstraction and the implementation in the Bridge pattern.

[edit] Strategy Pattern and Open Closed Principle

Strategy.JPG

According to Strategy pattern, the behaviors of a class should not be inherited, instead they should be encapsulated using interfaces. As an example, consider a car class. Two possible behaviors of 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. This may not be a concern when there are only a small number of models, but 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. Specific classes encapsulate 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();

This gives greater flexibility in design and is in harmony with the Open/closed principle (OCP) that states classes should be open for extension but closed for modification.

[edit] See also

[edit] External links

Personal tools
Namespaces
Variants
Actions
Navigation
Interaction
Toolbox
Print/export
Languages