美文网首页
S20. 模板方法模式

S20. 模板方法模式

作者: 拂去尘世尘 | 来源:发表于2022-05-03 12:32 被阅读0次

    模板方法

    模板方法模式是一种行为设计模式, 它在超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。

    模板方法模式利用C++多态特征,在父类定义一套结构流程,其中通用部分在父类实现,子类继承父类实现差异性的接口。

    意义

    模板方法模式是比较实用的一种设计模式,将不变部分的流程和接口在父类实现,变化部分的接口预留出来交由子类实现。如此,有利于代码的复用性、可扩展性。

    应用场景

    一位头痛和一位胃疼的病人去医院看病。

    分析

    现在有两位不同症状的病人去看病,可以自实现两套去不同科室的流程。假如10个、20个不同症状的病人,按照这种设计,代码工作量大不说还会存在大量的重复逻辑代码。遇到这种重复代码,就要想办法抽象。

    1. 先抽象出看病流程,所有病人去医院看病的流程都是一致的。无非是: 出示健康码、填表、挂号、医生面诊和缴费。

    2. 其中不同症状的病人看病流程一致,至于每个环节的内容是有些差异的。可交由子类多态实现。

    类图

    模板方法模式.png
    • CSeeDoctorTempateMethod: 看医生基类。实现通用的看病流程,声明必要的接口。
    • CTreatStomach: 看胃病子类。继承看病流程,根据自身实现具体接口。
    • CTreatHeadache: 看头痛子类。继承看病流程,根据自身实现具体接口。

    源码实现

    编程环境

    1. 编译环境: Linux环境
    2. 语言: C++语言
    3. 编译命令: make

    工程结构

    TemplateMethod/
    ├── main.cc
    ├── Makefile
    ├── see_doctor.cc
    └── see_doctor.h
    
    • see_doctor: 看医生具体的逻辑业务
    • main.cc: 客户端代码,程序入口
    • Makefile: 编译工具

    看医生基类:

    class CSeeDoctorTemplate
    {
    public:
        CSeeDoctorTemplate();
    
        ~CSeeDoctorTemplate();
    
        // 看病流程
        virtual void StartProcess() final;
    
        // 展示健康码
        virtual void ShowHealthCode();
    
        // 填写登记表
        virtual void FillTable() = 0;
    
        // 挂号
        virtual void Register() = 0;
    
        // 医生面诊
        virtual void SeeDoctor();
    
        // 付款
        virtual void Pay();
    
    public:
        float mCost;
    };
    

    通用流程接口实现:

    // 看病流程
    void CSeeDoctorTemplate::StartProcess()
    {
        this->ShowHealthCode();
        this->FillTable();
        this->Register();
        this->SeeDoctor();
        this->Pay();
    }
    

    此基类定义出通用的流程和接口,子类只需要继承基类实现具体的接口即可。


    看胃病

    class CTreatStomach : public CSeeDoctorTemplate
    {
    public:
        CTreatStomach();
    
        ~CTreatStomach();
    
        void FillTable();
    
        void Register();
    
        void SeeDoctor();
    };
    

    CTreatStomach继承CSeeDoctorTemplate,并实现具体有差异的几个接口即可。

    客户端代码

    int main(int argc, char *argv[])
    {
        shared_ptr<CSeeDoctorTemplate> p1(new CTreatStomach);
        p1->StartProcess();
    
        MAIN_LOG("\n\n");
    
        shared_ptr<CSeeDoctorTemplate> p2(new CTreatHeadache);
        p2->StartProcess();
    
        return 0;
    }
    

    测试效果

    -------- Treat Stomach --------
    Show health code! 
    Fill table: Stomach.
    Register Internal Medicine.
    See physician internist.
    Pay the medical bills 230.90¥.
    
    
    -------- Treat Headache --------
    Show health code! 
    Fill table: Headache.
    Register Surgery.
    See surgeon.
    Pay the medical bills 82.70¥.
    

    总结

    • 当希望客户端扩展某个特定算法步骤, 而不是整个算法或其结构时, 可使用模板方法模式。
      模板方法将整个算法转换为一系列独立的步骤, 以便子类能对其进行扩展, 同时还可让超类中所定义的结构保持完整。

    • 当多个类的算法除一些细微不同之外几乎完全一样时, 可使用该模式。 但其后果就是, 只要算法发生变化, 你就可能需要修改所有的类。
      在将算法转换为模板方法时, 可将相似的实现步骤提取到超类中以去除重复代码。子类间各不同的代码可继续保留在子类中。

    • 本例程为了方便没有将基类独立出来,实际应用应将此放在独立的头文件中,方便引用。

    相关文章

      网友评论

          本文标题:S20. 模板方法模式

          本文链接:https://www.haomeiwen.com/subject/acgbyrtx.html