设计模式 之 模板方法

本文详细介绍了模板方法设计模式,包括模式的定义、解决的问题、代码结构、设计原则和扩展方式,并通过实例展示了其具体应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义

模板方法(Template Method)是一种行为型设计模式,它定义了一个算法的骨架,将一些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

在模板方法模式中,定义一个操作中的算法骨架,而将一些步骤延迟到子类中实现。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。模板模式就像一个模板,我们只需要根据自己的需要填充相应的内容就可以了。

解决问题

稳定点:算法骨架
变化点:子流程需要变化
例如,我们可以定义一个抽象的爬山活动模板,模板中包含了准备活动、进行活动、结束活动等步骤,然后让具体的爬山活动子类去实现准备装备、选择路线等具体步骤。这样可以保证整个爬山活动的框架结构不变,但是每个具体的爬山活动可以根据实际情况进行个性化的定制。

代码结构

模板方法模式中包含两类角色:
1.抽象模板(Abstract Template)角色:定义抽象方法和具体方法,具体方法可以调用抽象方法,定义算法的骨架。
2.具体模板(Concrete Template)角色:实现抽象模板中的抽象方法,完成算法中的某些步骤。

设计原则

	单一职责
	开闭
	依赖倒置:子类扩展时,依赖基类的虚函数实现;使用者只依赖接口
	封装变化点:protected
	接口隔离
	最小知道

如何扩展

	实现子类继承基类,复写子流程
	通过多态调用方式使用

案例

某个品牌动物园,有一套固定的表演流程,但是其中有若干个表演子流程可创新替换,以尝试迭代更新表演流程。
一般实现方法:
#include <iostream>
using namespace std;

class ZooShow {
public:
    ZooShow(int type = 1) : _type(type) {}

public:
	//主流程:Show0()表演完,有时间继续PlayGame(),否则直接Show1()、Show2()、Show3()依次执行。
    void Show()
     {
        if (Show0())
        {
            PlayGame();
        }
        Show1();
        Show2();
        Show3();
    }

private:
    void PlayGame() {
        cout << "after Show0, then play game" << endl;
    }
	//Show0()环节需要根据日期来调整表演内容
    bool Show0() 
    {
        if (_type == 1) 
        {
            // 
            return true;
        } else if (_type == 2 ) 
        {
            //  ...
        } 
		//....
        cout << _type << " show0" << endl;
        return true;
    }

    void Show1() 
    {
        if (_type == 1) 
        {
            cout << _type << " Show1" << endl;
        } else if (_type == 2)
         {
            cout << _type << " Show1" << endl;
        } else if (_type == 3) 
        {
			//......
        }
    }

    void Show2() {
        if (_type == 1) 
        {
            cout << "base Show2" << endl;
        }
        else if (_type == 2)
         {
            cout << _type << " Show1" << endl;
        }
    }

    void Show3() 
    {
        if (_type == 1) 
        {
            cout << _type << " Show1" << endl;
        } else if (_type == 2) 
        {
            cout << _type << " Show1" << endl;
        }
        //......
    }
private:
    int _type;
};


int main () {
    ZooShow *zs = new ZooShow(1);
    zs->Show();
    return 0;
}
但是如果想要修改某个若个或多个表演子流程,就需要在对应的子流程中增加if语句,或者修改某些if语句里的代码,整体很不稳定。
基于模板方法,改进后:
//将主流程(稳定点)抽象成单独一个类,将子流程接口设置为protected,以便子类重写。
#include <iostream>
using namespace std;
class ZooShow {
public:
    void Show() 
    {
        // 如果子表演流程没有超时的话,进行一个中场游戏环节;如果超时,直接进入下一个子表演流程
        if (Show0())
        {
        	PlayGame();
      	}
        Show1();
        Show2();
        Show3();
    }
private:
    void PlayGame() 
    {
        cout << "after Show0, then play game" << endl;
    }
    bool expired;
protected: // 对其他用户关闭,但是子类开放的
    virtual bool Show0() 
    {
        cout << "show0" << endl;
        if (! expired)
         {
            return true;
        }
        return false;
    }
    virtual void Show1() { cout << "show1" << endl;}
    virtual void Show2() { cout << "show2" << endl; }
    virtual void Show3() { cout << "show3" << endl;}
};

// 想要修改子流程,只需要新增一个集成主流程的类,重新实现想要修改的子流程即可。
//例如:周一需要修改Show0() 流程的表演内容,其它流程不变
class ZooShowEx0: public ZooShow {
protected:
    virtual void Show0() 
    {
        if (! expired) 
        {
            return true;
        }
        return false;
    }
}
//例如:周二需要修改Show0() 、Show2()流程的表演内容,其它流程不变
class ZooShowEx1 : public ZooShow 
{
protected:
    virtual bool Show0() 
    {
        cout << "ZooShowEx1 show0" << endl;
        if (! expired) // 里氏替换
        { 
            return true;
        }
        return false;
    }
    virtual void Show2()
    {
        cout << "show3" << endl;
    }
};

class ZooShowEx2 : public ZooShow {
protected:
    virtual void Show1()
    {
        cout << "show1" << endl;
    }
    virtual void Show2()
    {
        cout << "show3" << endl;
    }
};

class ZooShowEx3 : public ZooShow {
protected:
    virtual void Show1()
    {
        cout << "show1" << endl;
    }
    virtual void Show3()
    {
        cout << "show3" << endl;
    }
    virtual void Show4() 
    {
        //
    }
};
/*
*/
int main () 
{
	//根据日期,创建不同表演对象进行表演
    ZooShow *zs = new ZooShowEx0; 
    // ZooShow *zs1 = new ZooShowEx1;
    // ZooShow *zs2 = new ZooShowEx2;
    zs->Show();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值