Design Patterns - Strategy

design-patterns

Design Patterns - Behavioral - Strategy:

In Strategy pattern, a class behavior or its algorithm can be changed at run 
time. This type of design pattern comes under behavior pattern.  In Strategy 
pattern, we create objects which represent various strategies and a context 
object whose behavior varies as per its strategy object. The strategy object 
changes the executing algorithm of the context object.

We are going to create a Strategy interface defining an action and concrete 
strategy classes implementing the Strategy interface. Context is a class which 
uses a Strategy.

// Step 1: Create an interface.
public interface Strategy {
   public int doOperation(int num1, int num2);
}

// Step 2: Create concrete classes implementing the same interface.
public class OperationAdd implements Strategy {
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}

public class OperationSubstract implements Strategy {
   public int doOperation(int num1, int num2) {
      return num1 - num2;
   }
}

public class OperationMultiply implements Strategy {
   public int doOperation(int num1, int num2) {
      return num1 * num2;
   }
}

// Step 3: Create Context Class.
public class Context {
   private Strategy strategy;

   public Context(Strategy strategy){
      this.strategy = strategy;
   }

   public int executeStrategy(int num1, int num2){
      return strategy.doOperation(num1, num2);
   }
}

// Step 4: Use the Context to see change in behaviour when it changes its Strategy
Context context = new Context(new OperationAdd());        
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

context = new Context(new OperationSubstract());        
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

context = new Context(new OperationMultiply());        
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));

With the strategy pattern you encapsulate specific families of algorithms 
allowing the client class responsible for instantiating a particular algorithm 
to have no knowledge of the actual implementation. There are several variations 
on the strategy pattern, the simplest of which is outlined below:

interface OutputInterface {
    public function load();
}

class SerializedArrayOutput implements OutputInterface {
    public function load() {
        return serialize($arrayOfData);
    }
}

class JsonStringOutput implements OutputInterface {
    public function load() {
        return json_encode($arrayOfData);
    }
}

The above code includes one interface, and 2 concrete class that implement that 
interface, but additional concrete class can be added. By encapsulating the 
above algorithms you are making it nice and clear in your code that other 
developers can easily add new output types without affecting the client code.  
This serves two purposes:

1. primarily it provides a simple contract which must be obeyed by any 
   new concrete implementations.
2. by implementing a common interface you can now utilise Type Hinting to 
   ensure that the client which is utilising these behaviours is of the correct 
   type in this case ‘OutputInterface’.

The next snippet of code outlines how a calling client class might use one of 
these algorithms and even better set the behaviour required at runtime:

class SomeClient {
    private $output;
    public function setOutput(OutputInterface $outputType) {
        $this->output = $outputType;
    }

    public function loadOutput() {
        return $this->output->load();
    }
}

The calling client class above has a private property which must be set at 
runtime and be of type ‘OutputInterface’ once this property is set a call to 
loadOutput() will call the load() method in the concrete class of the output 
type that has been set.

$client = new SomeClient();

// Want an array?
$client->setOutput(new ArrayOutput());
$data = $client->loadOutput();

// Want some JSON?
$client->setOutput(new JsonStringOutput());
$data = $client->loadOutput();

As you can see, the SomeClient class has no knowledge of the specific concrete 
class that is being used.
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License