赞
踩
典型模式:Template Method、Strategy、Observer/Event
定义一个操作中的算法的骨架(稳定),而将一些步骤延迟(变化)到子类中。Template Method 使得子类可以不改变(复用)一个算法的结构即可重定义(override重写)该算法的某些特定步骤。
——《设计模式》GoF
// 代表库函数 class Library{ public: // 稳定 template method void run(){ step1(); if(step2()){//支持变化==>虚函数的多态调用 step3(); } for (int i = 0; i < 4; i++){ step4(); //支持变化 ==> 虚函数的多态调用 } step5(); } virtual ~Library(){} protected: void Stepl(){ //稳定 //..... } void Step3(){//稳定 //..... } void Step5(){ //稳定 //... } virtual bool Step2() = 0;//变化 virtual void step4() = 0;//变化 }; // 代表调库的应用(程序开发) class Application : Library{ public: virtual bool step2(){ //子类重写具体实现... } virtual void step4(){ //子类重写具体实现... } }; int main(){ Library* pLib = new Application(); lib.run(); delete pLib; }
个人觉得模板方法模式使得类具有了更好的封装性,提供出了更加简单的实现接口。通过多态将早绑定转换为晚绑定、编译时绑定转换为运行时绑定,使得类库的使用更加方便灵活,便于使用。
定义一系列算法,把算法一个个封装起来,并且使它们可互相替换(变化)。该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)。
——《设计模式》GoF
//税收计算策略(方式) class Taxstrategy{ public: //Context代表上下文信息 virtual double calculate(const Context& context) = 0; virtual ~Taxstrategy(){} }; class CNTax : public TaxStrategy{ public: virtual double Calculate(const Context& context){ //中国税收计算... } }; class USTax : public Taxstrategy{ public: virtual double Calculate(const Context& context){ //美国税收计算... } }; // 扩展时无需改变原有代码 class DETax : public Taxstrategy{ public: virtual double Calculate(const Context& context){ //德国税收计算... } }; class Salesorder{ private: TaxStrategy* strategy; public: salesorder(strategyFactory* strategyFactory)( this->strategy = strategyFactory->Newstrategy() } ~SalesOrder(){ delete this->strategy; } public double CalculateTax(){ //... Context context(); double val = strategy->Calculate(context); //... } };
Strategy模式将策略(算法)封装成一个个对象,并继承自同一个基类,然后再通过多态指针动态的指定某个策略,使得整个代码扩展更加灵活,且不会影响客户程序的使用。
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
——《设计模式》GoF
class IProgress{ public: virtual void DoProgress(float value) = 0; virtual ~IProgress(){} }; // 文件分割器(将大文件分割成n个小文件) class FileSplitter { string m_filePath; int m_fileNumber; //ProgressBar* m_progressBar;//具体通知控件 List<IProgress*> m_iProgressList;//抽象通知机制,支持多个观察者 public: FileSplitter(const string& filePath, int fileNumber, ProgressBar* progressBar): m_filePath(filePath), m_fileNumber(fileNumber){ } void split(){ //1.读取大文件 //2.分批次向小文件中写入 for (int i - 0; i < m_fileNumber; i++){ //... float progressValue = m_fileNumber; progressValue = (i + 1) / progressValue; //计算目前进度 onProgress(progressValue);//发布通知 } } //添加观察者(订阅) void addIProgress(IProgress* iProgress){ m_iProgressList.add(iProgress); } //移除观察者(取消订阅) void removeIProgress(IProgress* iProgress){ m_iProgressList.remove(iProgress); } protected: virtual void onProgress(float value){ List<IProgress* >::Iterator itor = m_iProgressList.begin(); //每一个订阅者执行相应操作 while(itor != m_iProgressList.end()){ (*itor)->DoProgress(value); itor++; } } }; //主界面类 class MainForm : public Form, public IProgress{ TextBox*txtFilePath; TextBox*txtFileNumber; ProgressBar* progressBar; public: void Button1_click(){ string filePath = txtFilePath->getText(); int number = atoi(txtFileNumber->getText().c_str()); FileSplitter splitter(filePath, number); splitter.addIProgress(this);//订阅 splitter.split(); splitter.removeIProgress(this);//取消订阅 } virtual void DoProgress(float value){ progressBar->setValue(value); } };
观察者模式早闻大名,在框架之中运用广泛。经过学习可以发现,观察者模式将原本的依赖关系发生转变,不在依赖于实现细节,转而依赖抽象接口。
如果在FileSplitter中直接定义一个具体的通知方式(如progressBar),那么不仅无法做到通知多个观察对象,而且这个通知被限定死了,将来要添加新的订阅者或者更换新的通知展示形式都需要更改FileSplitter类本身,造成紧耦合。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。