“组件协作”模式:
现代软件专业分工之后的第一个结果是“框架与应用程序的划分”,“组件协作”模式通过晚期绑定,来实现框架与应用 程序之间的松耦合,是二者之间协作时常用的模式。
分 框架(app) 和 应用程序(lib)
晚绑定
松耦合
典型模式
- Template method(模板方法)
- Strategy(策略)
- Observer / Event(观察者)
Template Method
动机(Motivation)
在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架和应用程序之间的关系)而无法和任务的整体结构同时实现。
如何在确定稳定操作结构的前提下,来灵活应对各个子步骤灵活变化或者晚期实现需求?
下面通过代码来说明:
//template1_lib.cpp
//程序库开发人员
class Library
{
public:
//改进:具体方法步骤执行流程封装成一个Run()方法为public
//其余Step*方法修改为private 或者protected.
void Step1()
{
//...
}
void Step3()
{
//...
}
void Step5()
{
//...
}
};
//template1_app.cpp
//应用程序开发人员
class Application
{
public:
bool Step2()
{
//...
}
void Step4()
{
//...
}
};
int main()
{
Library lib();
Application app();
lib.Step1();
if (app.Step2())
{
lib.Step3();
}
for (int i = 0; i < 4; i++)
{
app.Step4();
}
lib().Step5();
}
//template2_lib.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()
{
//稳定
//...
}
//Step2 Step4 留给子类去写
//写上去但是不做实现
virtual bool Step2() = 0;//变化部分的做成虚函数
virtual void Step4() = 0;//变化部分的做成虚函数
};
//template2_app.cpp
//应用开发人员
//这个地方为什么要使用继承?原本两个没有太多交集独立的类,现在耦合度更高了?
//为什么不用组合的方式呢?
class Application:: public Library
{
protected:
virtual bool Step2()
{
//子类重写实现
}
virtual void Step4()
{
//子类重写实现
}
};
int main()
{
//每个含有虚函数的类拥有一个虚表,
//该类声明的对象内部保存一个虚指针
//当父类指针指向子类对象时,则子类的虚表中对应的函数地址就替换到父类对象(pLib)的虚表中对应的位置了。
//这个
Library* pLib = new Application();
pLib->Run();
delete pLib;
}
程序主流程调用红色部分
程序主流程调研功能蓝色部分
模式定义
定义一个操作中的算法的骨架(稳定),而将一些步骤延迟(变化)到子类中。Template Method 使得子类可以不改变(复用)一个算法的结构即可重定义(override 重写)该算法的某些特定步骤。
延迟到子类:指的就是定义一个虚函数,让子类去实现这个虚函数,让支持子类去变化
不改变:就是复用。
两种极端情况:
1.所有条件都变化就不适合用任何模式,必须有稳定的部分
2.所有都是不变的也不需要用设计模式。
设计模式最大的作用就是在变化和稳定中间寻找隔离点
把变化的小兔子关到笼子里面,不至于跳出来把整个房间给污染掉。
一个正常的软件体系结构,一定是既有变化又有稳定点的部分。
核心:要分辨出来软件体系结构里面那些是稳定的,那些是变化的。
再看
红色部分:稳定的
蓝色部分:变化的
要点总结
Template Method 模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用。它用最简洁的机制(虚函数的多态性)为很多应用程序框架提供了灵活的扩展点,是代码复用方面的基本实现结构。
非常基础、只要你写过面向对象的程序,一定会用到Template Method的设计模式
扩展:继承+ 多态+虚函数,由子类继承父类。然后对子类进行override。
除了可以灵活应对子步骤的变化外,“不要调用我,让我来调用你”的反向控制结构是Template Method的典型应用
反向结构:通过虚函数晚绑定机制。晚绑定机制还有函数指针
在具体实现方面,被Tempate Method调用的虚方法可以具有实现,也可以没有实现(抽象方法、纯虚函数方法),但一般推荐将他们设置为protected方法。
往往放到一个流程里面才有意义。
protected:
PrimitiveOperation1();
PrimitiveOperation2();
模式很简单,需要思考 变化和稳定之间的这个力量的关系,后面越来越复杂的模式也离不开变化点和稳定点的关系把握。
文章为用户上传,仅供非商业浏览。发布者:Lomu,转转请注明出处: https://www.daogebangong.com/articles/detail/she-zhi-mo-shi-mo-ban-mo-shi-Template-Method.html
评论列表(196条)
测试