• extracted implementation details(SRP)
  • created opportunity for easy change and easy extension
  • reduced duplication(DRY)
  • Linux Virtual File System?

Example 1

底下的例子中,SortingContext 為 client 端(在此為 main)的 interface,client 可使用不同的 SortingStrategy ,SortingStrategy 是可抽換的,其子類別為不同的 sorting algorithm,將子類別當作參數傳入 SortingContext 裡的 member function 是安全的,因為子類別 pointer 轉成其 parent 類別的 pointer 是安全的。

#include <vector>
#include <memory>
#include <iostream>
 
class SortingStrategy 
{
public:
 
    SortingStrategy(){}
    virtual ~SortingStrategy(){}
    virtual void sort(std::vector<int>& A){}
};
 
 
class BubbleSortStrategy : public SortingStrategy 
{
public:
    void sort(std::vector<int>& A) override 
    {
        std::cout << "Sorting using Bubble Sort \n";
    }
};
 
class MergeSortStrategy : public SortingStrategy
{
public:
    void sort(std::vector<int>& A) override 
    {
        std::cout << "Sorting using Merge Sort \n";
    }
};
 
class SortingContext {
private:
    std::unique_ptr<SortingStrategy> sortingStrategy;
public:
    SortingContext(std::unique_ptr<SortingStrategy> strategy): 
        sortingStrategy(std::move(strategy)) {}
 
    void setSortingStrategy(std::unique_ptr<SortingStrategy> strategy) {
        this->sortingStrategy = std::move(strategy);
    }
    
    void performSort(std::vector<int>& array) {
        sortingStrategy.get()->sort(array);
    }
};
 
int main() {
 
    SortingContext* sortingContext = new SortingContext(std::make_unique<BubbleSortStrategy>());
    std::vector<int> array1 = {5, 2, 9, 1, 5};
    sortingContext->performSort(array1); 
 
    // Change strategy to MergeSortStrategy
    sortingContext->setSortingStrategy(std::make_unique<MergeSortStrategy>());
    std::vector<int> array2 = {8, 3, 7, 4, 2};
    sortingContext->performSort(array2); // Output: Sorting using Merge Sort
}

要注意這邊不能使用 this->sortingStrategy.reset(strategy.get()) ,會造成 double free,因為上一個 strategy 因為本身就是 unique pointer,因此已經自動被 free 了。

this->sortingStrategy = std::move(strategy);

Example 2

#include <memory>
#include <iostream>
 
class Shape {
public:
  Shape() = default;
  virtual ~Shape() = default;
  virtual void draw() = 0;
};
 
class DrawStrategy {
public:
  DrawStrategy(){}
  virtual ~DrawStrategy(){}
  virtual void draw(Shape& shape){};
};
 
class DrawSquareStrategy : public DrawStrategy
{
public:
  void draw(Shape& square) override 
  {
    std::cout << "Drawing an Circle! \n";
  }
};
 
class DrawCircleStrategy : public DrawStrategy
{
public:
  void draw(Shape& circle) override
  {
    std::cout << "Drawing an Square! \n";
  }
};
 
class Circle : public Shape
{
private:
  std::unique_ptr<DrawCircleStrategy> drawing;
public:
  Circle(std::unique_ptr<DrawCircleStrategy> strategy):
    drawing(std::move(strategy)) {}
 
  void draw() override {
    drawing->draw(*this);
  }
};
 
class Square : public Shape
{
private:
  std::unique_ptr<DrawSquareStrategy> drawing;
public:
  Square(std::unique_ptr<DrawSquareStrategy> strategy):
    drawing(std::move(strategy)) {}
 
  void draw() override {
    drawing->draw(*this);
  }
};
 
 
int main() {
  Square* s1 = new Square(std::make_unique<DrawSquareStrategy>());
  Circle* c1 = new Circle(std::make_unique<DrawCircleStrategy>());
  s1->draw();
  c1->draw();
}