改善丑陋的代码–并列if-else语句优化(策略模式)

Aki 发布于 2022-11-10 201 次阅读


C++设计模式02-——策略设计模式-pudn.com

例如有以下的代码:

double Add(double a, double b)
{
    return a + b;
}

double Sub(double a, double b)
{
    return a - b;
}

double Mul(double a, double b)
{
    return a * b;
}

double Div(double a, double b)
{
    assert(b != 0);
    return a / b;
}

using func_ptr = double(*)(double, double);


int main()
{
    
    map<string, func_ptr> func_table = { {"add",Add},{"sub",Sub},{"mul",Mul},{"div",Div} };

    auto end = func_table.end();
    string tmp;
    while(1)
    {
      cin >> tmp;
      auto res = func_table.find(tmp);
      if (res != end)
      {
          cout << res->second(10, 20) << endl;
      }
    }    

    return 0;
}

上面的是一种映射表的做法,下面展示的是多态类的策略模式做法。

class Algorithm
{
public:
   Algorithm(){}
   virtual ~Algorithm()noexcept{}
   virtual double func(double a, double b) = 0;
};

class Add :public Algorithm
{
public:
    virtual double func(double a, double b)
    {
        return a + b;
    }
};

class Sub :public Algorithm
{
public:
    virtual double func(double a, double b)
    {
        return a - b;
    }
};

class Mul :public Algorithm
{
public:
    virtual double func(double a, double b)
    {
        return a * b;
    }
};

class Div :public Algorithm
{
public:
    virtual double func(double a, double b)
    {
        assert(b != 0);
        return a / b;
    }
};

class manager
{
public:
    manager()
    {
        //构造函数什么都没做,因为智慧指针初始化时就会置空
    }

    manager(Algorithm* p)
    {
        ptr.reset(p);  //释放原来管理的指针,更新新的指针指向
    }

    void set_func(Algorithm* p)
    {
        ptr.reset(p);  //释放原来管理的指针,更新新的指针指向
    }

    void call(double a,double b)
    {
        cout << ptr->func(a, b) << endl;
    }
    ~manager()noexcept{}
private:
    unique_ptr<Algorithm> ptr;  //使用了智慧指针来代替原始指针,更安全方便
};


int main()
{
    
    unique_ptr<manager>p(make_unique<manager>());
    p->set_func(new Add());
    p->call(10, 20);
    p->set_func(new Sub());
    p->call(10, 20);
    p->set_func(new Mul());
    p->call(10, 20);
    p->set_func(new Div());
    p->call(10,20);
   
    return 0;
}

策略模式包括:

  • Strategy(策略)Strategy角色负责决定实现策略所必需的接口(API)。
  • ConcreteStrategy(具体的策略)ConcreteStrategy角色负责实现Strategy角色的接口(API),即负责实现具体的策略(战略、方向、方法和算法)。
  • Context(上下文)负责使用Strategy角色。Context角色保存了ConcreteStrategy角色的实例,并使用ConcreteStrategy角色去实现需求(总之,还是要调用Strategy角色的接口(API))

当我们想要添加新的策略时只需要添加新的策略类继承接口类,然后在类中添加具体的策略就行了。这个方法更加符合我们面向对象的方法。