Computer Science Design Patterns/Strategy
Examples
Ruby
class Context def initialize(strategy) extend(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 a.execute #=> Doing the task the normal way c = Context.new(StrategyC) c.execute #=> Doing the task even more alternatively
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
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))
Java
/** 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 Add implements Strategy { public int execute(int a, int b) { System.out.println("Called Add's execute()"); return a + b; // Do an addition with a and b } }
class Subtract implements Strategy { public int execute(int a, int b) { System.out.println("Called Subtract's execute()"); return a - b; // Do a subtraction with a and b } }
class Multiply implements Strategy { public int execute(int a, int b) { System.out.println("Called Multiply'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; public Context(Strategy strategy) { this.strategy = strategy; } public int executeStrategy(int a, int b) { return this.strategy.execute(a, b); } }
/** Tests the pattern */ class StrategyExample { public static void main(String[] args) { Context context; // Three contexts following different strategies context = new Context(new Add()); int resultA = context.executeStrategy(3, 4); context = new Context(new Subtract()); int resultB = context.executeStrategy(3, 4); context = new Context(new Multiply()); int resultC = context.executeStrategy(3, 4); System.out.println("Result A : " + resultA ); System.out.println("Result B : " + resultB ); System.out.println("Result C : " + resultC ); } }
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
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"
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
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"
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 = submit_func; }; 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);
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; }
C++
Similar to Java, but does not require dynamic allocation of objects.
#include <iostream> class Strategy { public: virtual int execute (int a, int b) = 0; }; class ConcreteStrategyAdd:public Strategy { public: int execute(int a, int b) { std::cout << "Called ConcreteStrategyAdd's execute()\n"; return a + b; } }; class ConcreteStrategySubstract:public Strategy { public: int execute(int a, int b) { std::cout << "Called ConcreteStrategySubstract's execute()\n"; return a - b; } }; class ConcreteStrategyMultiply:public Strategy { public: int execute(int a, int b) { std::cout << "Called ConcreteStrategyMultiply's execute()\n"; return a * b; } }; class Context { private: Strategy* pStrategy; public: Context (Strategy& strategy) : pStrategy(&strategy) { } void SetStrategy(Strategy& strategy) { pStrategy = &strategy; } int executeStrategy(int a, int b) { return pStrategy->execute(a,b); } }; int main() { ConcreteStrategyAdd concreteStrategyAdd; ConcreteStrategySubstract concreteStrategySubstract; ConcreteStrategyMultiply concreteStrategyMultiply; Context context(concreteStrategyAdd); int resultA = context.executeStrategy(3,4); context.SetStrategy(concreteStrategySubstract); int resultB = context.executeStrategy(3,4); context.SetStrategy(concreteStrategyMultiply); int resultC = context.executeStrategy(3,4); std::cout << "resultA: " << resultA << "\tresultB: " << resultB << "\tresultC: " << resultC << "\n"; }
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); } } }
C# using interfaces
using System; namespace Wikipedia.Patterns.Strategy { // The strategy we will implement will be // to advise on investments. interface IHasInvestmentStrategy { long CalculateInvestment(); } // Here we have one way to go about it. class FollowTheMoon : IHasInvestmentStrategy { protected virtual int MoonPhase { get; set; } protected virtual int AstrologicalSign { get; set; } public FollowTheMoon(int moonPhase, int yourSign) { MoonPhase = moonPhase; AstrologicalSign = yourSign; } public long CalculateInvestment() { if (MoonPhase == AstrologicalSign) return 1000; else return 100 * (MoonPhase % DateTime.Today.Day); } } // And here we have another. // Note that each strategy may have its own dependencies. // The EverythingYouOwn strategy needs a bank account. class EverythingYouOwn : IHasInvestmentStrategy { protected virtual OtherLib.IBankAccessor Accounts { get; set; } public EverythingYouOwn(OtherLib.IBankAccessor accounts) { Accounts = accounts; } public long CalculateInvestment() { return Accounts.GetAccountBalancesTotal(); } } // The InvestmentManager is where we want to be able to // change strategies. This is the Context. class InvestmentManager { public IHasInvestmentStrategy Strategy { get; set; } public InvestmentManager(IHasInvestmentStrategy strategy) { Strategy = strategy; } public void Report() { // Our investment is determined by the current strategy. var investment = Strategy.CalculateInvestment(); Console.WriteLine("You should invest {0} dollars!", investment); } } class Program { static void Main() { // Define some of the strategies we will use. var strategyA = new FollowTheMoon( 8, 8 ); var strategyB = new EverythingYouOwn( OtherLib.BankAccountManager.MyAccount); // Our investment manager var manager = new InvestmentManager(strategyA); manager.Report(); // You should invest 1000 dollars! manager.Strategy = strategyB; manager.Report(); // You should invest 13521500000000 dollars! } } }
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(); } } }
PHP
<?php interface IStrategy { public function execute(); } class Context { private $strategy; public function __construct(IStrategy $strategy) { $this->strategy = $strategy; } public function execute() { $this->strategy->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 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(); } } new StrategyExample(); ?>
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;
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
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