策略模式

<image>

在電腦編程中，策略模式（strategy pattern，也叫做policy pattern），是一種行為型軟體設計模式，它確使可以在運行時選擇算法。不再直接的實現一個單一的演算法，代碼接收運行時指令，選擇一個算法家族中的某個演算法。

## 概述

策略模式定義了一族可互換代替的演算法（業務規則），並封裝了每個演算法。

## 結構

<image>

在上面的UML類圖中，`Context`類不直接實現演算法。`Context`轉而提及`Strategy`接口來實行一個演算法（`strategy.algorithm()`），這使得`Context`獨立於演算法是如何是實現的。`Strategy1`和`Strategy2`類實現了`Strategy`接口，就是說實現（封裝）了一個演算法。

UML序列圖展示運行時交互：`Context`對象委託一個演算法至不同的`Strategy`對象。首先`Context`調用`algorithm()`於`Strategy1`對象之上，它實行演算法並將結果返回給`Context`。此後，`Context`變更它的策略並調用`algorithm()`在`Strategy2`對象之上，它實行一個演算法並將結果返回給`Context`。

## 示例

### C++

下面是C++的例子：

```cpp
#include <iostream>

using namespace std;

class StrategyInterface {
public:
    virtual void execute() = 0;
};

class ConcreteStrategyA: public StrategyInterface {
public:
    virtual void execute() {
        cout << "Called ConcreteStrategyA execute method" << endl;
    }
};

class ConcreteStrategyB: public StrategyInterface {
public:
    virtual void execute() {
        cout << "Called ConcreteStrategyB execute method" << endl;
    }
};

class Context {
private:
    StrategyInterface *_strategy;

public:
    Context(StrategyInterface *strategy):_strategy(strategy) {
    }

    void set_strategy(StrategyInterface *strategy) {
        _strategy = strategy;
    }

    void execute() {
        _strategy->execute();
    }
};

int main(int argc, char *argv[])
{
    ConcreteStrategyA concreteStrategyA;
    ConcreteStrategyB concreteStrategyB;

    Context contextA(&concreteStrategyA);
    Context contextB(&concreteStrategyB);

    contextA.execute();
    contextB.execute();
    
    contextA.set_strategy(&concreteStrategyB);
    contextA.execute();

    return 0;
}
```

### Java

下面是Java的例子：

```java
// The classes that implement a concrete strategy should implement this
// The context class uses this to call the concrete strategy
interface Strategy {
    void execute();
}

// Implements the algorithm using the strategy interface
class FirstStrategy implements Strategy {
    public void execute() {
        System.out.println("Called FirstStrategy.execute()");
    }
}

class SecondStrategy implements Strategy {
    public void execute() {
        System.out.println("Called SecondStrategy.execute()");
    }
}

// Configured with a ConcreteStrategy object and maintains a reference to a Strategy object
class Context {
    Strategy strategy;

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

    public void execute() {
        this.strategy.execute();
    }
}

//StrategyExample test application
class StrategyExample {
    public static void main(String[] args) {
        Context context;

        // Three contexts following different strategies
        context = new Context(new FirstStrategy());
        context.execute();

        context = new Context(new SecondStrategy());
        context.execute();
    }
}
```

### C#

下面是C#的例子：

```csharp
using System;

namespace Wikipedia.Patterns.Strategy {
    // The classes that implement a concrete strategy should implement this
    // 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()" );
        }
    }

    // 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 Execute() {
            strategy.Execute();
        }
    }

    // MainApp test application
    class MainApp {
        static void Main() {
            Context context;

            // Three contexts following different strategies
            context = new Context(new ConcreteStrategyA());
            context.Execute();

            context = new Context(new ConcreteStrategyB());
            context.Execute();
        }
    }
}
```

### Python

下面是Python的例子：

```python
from abc import ABC, abstractmethod

class Strategy(ABC):
    @abstractmethod
    def __call__(self): pass

class ConcreteStrategyA(Strategy):
    def __call__(self): 
        print("Called ConcreteStrategyA execute method")

class ConcreteStrategyB(Strategy):
    def __call__(self): 
        print("Called ConcreteStrategyB execute method")

class Context():
    def __init__(self, strategy):
        self.strategy = strategy
    def __call__(self):
        self.strategy()
```

其執行：

```pycon
>>> context = Context(ConcreteStrategyA())
>>> context()
Called ConcreteStrategyA execute method
>>> context = Context(ConcreteStrategyB())
>>> context()
Called ConcreteStrategyB execute method
```