设计模式第三讲--模板方法(Template Method)

1. 模式分类

从目的来看:

创建型模式

结构性模式

行为型模式

从范围来看:

类模式处理类与子类的静态关系。

对象模式处理对象间的动态关系。

从封装变化角度对模式分类:

组件协作:

Template Method

Strategy

Observer/Event

 

单一职责:

Decorator

Bridge

 

对象创建:

Factory Method

Abstact Factory

Prototype

Builder

 

对象性能:

Singleton

Flyweight

 

接口隔离:

Facade

Proxy

Mediator

Adapter

 

状态变化:

Memento

State

 

数据结构:

Composite

Iterator

Chain of

Resposibility

 

行为变化:

Command

Visitor

 

领域问题:

Interpreter

 

2. 重构获得模式 Refactoring to Patterns

面向对象设计模式是“好的面向对象设计”,所谓“好的面向对象设计”指的是那些可以满足“应对变化,提高复用”的设计。

 

现代软件设计的特征是“需求的频繁变化”。设计模式的要点在于“寻找变化点,然后在变化点处应用设计模式,从而来更好的应对需求的变化”。“什么时候、什么地点应用设计模式”比“理解设计模式结构本身”更为重要。

 

设计模式的应用不宜先入为主,一上来就是用设计模式是对设计模式最大误用。没有一步到位的设计模式。敏捷软件开发提倡的是Refactoring to Patterns”是目前公认的最好的设计模式的方法。

 

3. 重构关键技法

静态-->动态

早绑定-->晚绑定

继承-->组合

编译时依赖-->运行时依赖

紧耦合-->松耦合

 

4. “组件协作”模式

现代软件专业分工之后的第一个结果是“框架与应用程序的划分”,“组件协作”模式通过晚绑定,来实现框架与应用之间的松耦合,是两者之间协作时常用的模式。

 

经典模式:

Template Method

Strategy

Observer/Event

 

5. Template Method的动机

在软件构建过程中,对于某一项任务,他常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而无法和任务的整体结构同时实现。

 

如何在确定稳定操作结构的前提下,来灵活应对各个子步骤化的变化或者晚期实现需求?

 

6.代码

template1_lib.h文件内容

复制代码
 1 //程序库开发人员
 2 
 3 //如果在实际的项目中,方法应该在相应的cpp文件中实现
 4 class Library
 5 {
 6 public:
 7 
 8     void Step1()
 9     {
10         //...
11     }
12 
13     void Step3()
14     {
15         //...
16     }
17 
18     void Step5()
19     {
20         //...
21     }
22 };
复制代码

template1_app.h

复制代码
 1 #pragma once
 2 
 3 //应用开发人员
 4 
 5 //如果在实际的项目中,方法应该在相应的cpp文件中实现
 6 class Application
 7 {
 8 public:
 9     bool Step2()
10     {
11         //...
12     }
13 
14     void Step4()
15     {
16         //...
17     }
18 };
复制代码

Main1.cpp

复制代码
 1 //应用程序开发人员
 2 
 3 #include "template1_lib.h"
 4 
 5 #include "template1_app.h"
 6 
 7 int main()
 8 {
 9     Library lib;
10     Application app;
11 
12     lib.Step1();
13     if (app.Step2())
14     {
15         lib.Step3();
16     }
17     
18     for (int i = 0; i < 4; i++)
19     {
20         app.Step4();
21     }
22     
23     lib.Step5();
24 }
复制代码

7. 利用Template Method设计模式修改后的代码

template2_lib.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#pragma once
 
//程序库开发人员
 
//如果在实际的项目中,方法应该在相应的cpp文件中实现
class Library
{
public:
 
    //稳定template method
    void Run()
    {
        Step1();
        if (Step2())                        //支持变化===》虚函数的多态调用
        {
            Step3();
        }
 
        for (int i = 0; i < 4; i++)
        {
            Step4();                       //支持变化===》虚函数的多态调用
        }
 
        Step5();
    }
 
    virtual ~Library()     //虚的析构函数
    {
        //...
    }
protected:
 
    void Step1()   //稳定
    {
        //...
    }
 
    void Step3()   //稳定
    {
        //...
    }
 
    void Step5()   //稳定
    {
        //...
    }
 
    virtual bool Step2() = 0;  //变化
    virtual void Step4() = 0;  //变化
};

 template2_app.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#pragma once
 
#include "template2_lib.h"
 
class Application :public Library
{
protected:
    virtual bool Step2()
    {
        //...子类重写实现
    }
 
    virtual void Step4()
    {
        //...子类重写实现
    }
 
};

Main2.cpp

1
2
3
4
5
6
7
8
9
10
11
#include "template2_lib.h"
 
#include "template2_app.h"
 
int main()
{
    Library* pLib = new Application();
    pLib->Run();
 
    delete pLib;
}

  

8. 图

 

 

 

 

 

9. Template Method模式定义

定义一个操作中的算法的骨架(稳定),而将一些步骤延迟(变化)到子类中。Template Method使得子类可以不改变(复用)一个算法的结构即可重定义(override重写)该算法的某些特定步骤。稳定中有变化。当整个算法的骨架不稳定时,就不再适合Template Method

 

10. 结构

 

 

 

11. 要点总结

Template Method模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用。它用最简洁的机制(虚函数的多态调用)为很多应用程序框架提供了灵活的扩展点,是代码复用方面基本的实现结构。

 

除了可以灵活应对子步骤变化外,“不要调用我,让我来调用你”的反向控制结构是Template Method的典型应用场景。

 

在具体实现方面,被Template Method调用的虚函数方法可以实现,也可以没有任何实现(抽象方法、纯虚方法),一般推荐把它们设置为protected方法。

 

 

子类虚函数的晚绑定的实现机制就是虚函数表中挂了一个函数指针来实现的。

 

posted on   xcxfury001  阅读(40)  评论(0编辑  收藏  举报

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示