模板方法

模板方法

以下介绍几种常用的设计模式,既作复习,也是在开发实践中对于设计模式的再理解;

顺序并不按照主要教材所列,且有些内容掺杂个人理解,并非完全正确,欢迎交流探讨;

首先从模板方法开始;

目的

在开发中常会遇到这样的情况:自己写的库中,一个功能的流程是固定的,且大部分步骤具体实现也是固定的,但是其中某一些步骤的具体实现无法确定,是由使用该库的人进行开发,那么如何让别人使用该库时能够复用自己的代码呢?这就是模板方法的使用场景;

概念

模板方法:定义一个操作中稳定不变的算法骨架,将一些步骤延迟到变化的子类中,其目的是使得子类可以复用一个算法框架;

示例

在C++中,具体方法是,使用虚函数与继承实现模板方法,简单示例如下:

class Solver {   
public:    
    Solver() = default;
    virtual ~Solver() = default;
    
    void solve() 
    {        
        preprocess();        
        compute();        
        postprocess();    
    }
protected:    
    virtual void compute() 
    { 
        // 常常变化
        // ...
    }
private:    
    void preprocess() 
    { 
        // 稳定的实现
        // ...
    }    
    void postprocess() 
    { 
        // 稳定的实现
        // ...
    }
    
    // ...
};


class SolverA : public Solver {
protected:     
    virtual void compute() override 
    { 
        // SolverA 的计算过程
    }
    
    // ...
};

class SolverB : public Solver {    
protected:    
    virtual void compute() override 
    { 
        // SolverB 的计算过程
    }
    
    // ...
};

class SolverC : public Solver {    
protected:    
    virtual void compute() override 
    { 
        // SolverC 的计算过程
    }
    
    // ...
};

#include <vector>
#include <memory>

using std::vector
using std::unique_ptr;

int main() 
{
    unique_ptr<Solver> solA = std::make_unique<SolverA>();
    unique_ptr<Solver> solB = std::make_unique<SolverB>();
    // ...
    
    vector<unique_ptr<Solver>> sol;
    sol.push_back(std::move(solA));
    sol.push_back(std::move(solB));
    // ...
    
    for (int i = 0; i < sol.size(); ++i) {
        sol[i]->solve();
    }
    // ...
    
    return 0;
}

上述代码中,Solver包含:前处理,计算,后处理三个稳定的过程,其中前处理与后处理具体实现是固定的,但是“计算”因具体方法而异,所以使用模板方法,只需实现不同的计算方法即可, 而算法流程框架、前处理与后处理代码均得到复用;

参考

本文参考 同 本博客前述<面向对象设计>一文中所参考项;


本文作者: 王同学