zoukankan      html  css  js  c++  java
  • Template Method模式精解(C++版本)

    设计模式第三弹,设计模式行为型模式中的模板方法,也比较简单。

    使用情景

    当你只希望客户端扩展某个特定算法步骤, 而不是整个算法或其结构时, 可使用模板方法模式。模板方法将整个算法转换为一系列独立的步骤, 以便子类能对其进行扩展, 同时还可让超类中所定义的结构保持完整。可以设想我们上学时候临摹毛笔字,你可以使用墨汁沿着田字格中的汉字临摹,也可以使用红墨水临摹,无论用哪种颜色的墨水,最后完成的字的形状是一样的。

    图片来自网络

    汉字的字形就是模板,每个学生使用不同的工具或者墨水按照模板习字,就是模板方法。

    问题引入

    Template Method就是带有模板功能的模式,它有下面的特点:

    1. 组成模板的方法被定义在父类中,但是这些方法是抽象方法,具体的方法实现由各个子类实现;
    2. 父类中定义了处理流程的框架,这个流程由上面定义的这些方法按照特定的步骤完成

    打一个比方,如果我们村里的每个人盖一座房子,无论是谁都需要完成如下的步骤,准备材料,设计图纸,雇佣施工队,开工建设,完成这些步骤之后才能盖起一座完整的房子。但是不同的人使用的材料不同,设计的图纸不同,施工队的质量也不一样,依照主人的品味和资金实力每一个步骤不同的人做就有不同的效果。这里的所有步骤就是模板方法,不同的人就是子类。

    UML表示及代码

    参考《图解设计模式》中第三章的例子,UML图及代码如下所示


    每个类的作用如下

    • AbstractDisplay是抽象类,定义了整个的流程框架,即方法display(),该方法又由3个抽象方法实现open(), print(), close()
    • CharDisplayStringDisplay是具体的继承类,它们实现了抽象类中的抽象方法。
      仅仅从抽象类看不出来每个抽象方法的具体实现,这些方法由每个类具体负责,上面的所有的类的具体代码如下。
    #include <string>
    #include <iostream>
    using namespace std;
    class AbstractDisplay {
    public:
    	virtual void open() = 0;
    	virtual void print() = 0;
    	virtual void close() = 0;
    	virtual void display() final
    	{
    		open();
    		for (int i = 0; i < 5; i++) {
    			print();
    		}
    		close();
    	}
    };
    
    class CharDisplay: public AbstractDisplay {
    public:
    	CharDisplay(char ch = 'h') : ch_(ch) {};
    	void open() override
    	{
    		cout << "<<";
    	}
    	void close() override
    	{
    		cout << ">>
    ";
    	}
    	void print() override
    	{
    		cout << ch_;
    	}
    private:
    	char ch_;
    };
    
    class StringDisplay : public AbstractDisplay {
    public:
    	StringDisplay(string str = " ", int width = 10) :width_(width), str_(str) {};
    	void open() override
    	{
    		printLine();
    	}
    	void print() override
    	{
    		cout << "|" << str_ << "|
    ";
    	}
    	void close() override
    	{
    		printLine();
    	}
    private:
    	string str_;
    	int width_;
    	void printLine() const {
    		cout << "+";
    		for (int i = 0; i < width_; i++) {
    			cout << "-";
    		}
    		cout << "+
    ";
    	}
    };
    
    int main()
    {
    	AbstractDisplay* display = new CharDisplay('H');
    	display->display();
    	delete display;
    	display = new StringDisplay("Hello World!");
    	display->display();
    	delete display;
    	display = new StringDisplay("Hello haha!");
    	display->display();
    	delete display;
    
    	return 0;
    }
    

    运行结果如下,

    <<HHHHH>>
    +----------+
    |Hello World!|
    |Hello World!|
    |Hello World!|
    |Hello World!|
    |Hello World!|
    +----------+
    +----------+
    |Hello haha!|
    |Hello haha!|
    |Hello haha!|
    |Hello haha!|
    |Hello haha!|
    +----------+
    
  • 相关阅读:
    Dubbo学习记录(一)
    Quartz定调度简单案例
    oracle中批量生成字段类型的脚本
    MsSQLserver中修改字段值系统自动生成的脚本
    根据oracle的主键列生成SQLserver的主键
    SQLServer2005如何批量修改架构名
    win10 下oracle tns通过IP无法访问的解决办法
    PD PDM模型中关系设置为概念模型样式
    PB12.5.2安装
    Java Web 项目目录规范
  • 原文地址:https://www.cnblogs.com/bugxch/p/14723462.html
Copyright © 2011-2022 走看看