设计模式一直是面向对象软件设计中最重要的一个领域,围绕设计模式讨论的话题也是数不胜数,其中GOF表明的23种设计模式更是经典之著。这个系列中我将会从本身的理解出发,阐述每种设计模式的思想,做用和利弊。ios
1、 设计模式概念c++
要讲解设计模式,必然先要说清楚两个问题,算法
1.什么是设计模式?设计模式
2.为何须要设计模式?函数
对于设计模式,GOF是这么定义的:设计模式是对被用来在特定场景下解决通常设计问题的类和相互通讯的对象的描述,更特殊地,将之放到面向对象软件设计中来说,设计模式能够被认为是实践中总结出的设计经验,是系统中会重复出现的设计。ui
因此设计模式能够帮助咱们更加简单方便地复用成功的设计和体系结构,更具体地,为了得到最大限度地复用的关键在于新需求和已有需求发生变化时,系统设计有能力相应地改进,避免从新设计带来的巨大代价。每种设计模式都是经过确保系统以某种特定方式变化来得到这种可变能力,每个设计模式容许系统结构的某个方面独立于其余方面,从而对某一种特殊变化具备适应性。spa
这就引出了选择设计模式的方法:首先考虑系统在哪些方面具备可变性,选择的设计模式不会由于这些可变因素而引发从新设计。GOF根据设计模式完成的任务类型将其分为了建立型,结构型和行为型三大类,建立型模式用于对象的建立,结构型模式用于处理类或者对象的组合;行为型模式描述类或对象怎样交互和分配职责。同时根据范围模式分为类模式和对象模式,类模式处理类和子类之间的关系,经过继承建立,是静态的,编译期就肯定了;对象模式处理对象之间的关系,是动态的,运行时可变,具体分类如表格所示:prototype
|
建立型设计 |
结构型代理 |
行为型 |
类模式 |
Factory method |
Adapter |
Interpreter template method |
对象模式 |
Abstract factory builder prototype singleton |
Adapter bridge composite decorator facade flyweight proxy |
Chain of responsibility command iterator mediator memento observer state strategy visitor |
建立型类模式将对象的部分建立工做延迟到子类,建立型对象模式则延迟到另外一个对象中。结构型类模式使用继承机制来组合类,结构型对象模式则描述了对象的组合方式。行为类模式用继承描述算法和控制流,行为型对象模式则经过一组对象协做完成任务。另外咱们将会看到,在部分类模式中,经过引入参数或者模板类型能够避免建立子类。
本系列以建立型模式的factory method模式开始,逐个介绍GOF的23种设计模式。
2、 factory method模式
若是一个类不知道须要建立的对象的类型时,若是当前但愿子类来指定建立的对象类型时,若是但愿将建立对象的职责委托给子类并将这一代理过程局部化时,就能够考虑使用factory method模式。
下面以一个例子来讲明,这个例子也会在后续设计模式中屡次提到,因此请读者先记住一下。如今要开发一个芯片设计的软件,能够在掩模上设计不一样的图形。不一样的掩模会有不一样的参数,好比曝光方式,角度等,图形也能够会有不少种,在不影响理解的前提下咱们假设只有圆形,矩形和三角形三种图形,在不一样的掩模上画同一个图获得的效果是不同的。对于同一种掩模,咱们要获得一个能够画图的对象,至于画出的是圆形,矩形仍是三角形,子类才能知道,掩模只能拿到接口。类设计图以下:
具体代码实现以下:
//mask.hpp #ifndef MASK_HPP #define MASK_HPP class MaskFigure{ public: virtual ~MaskFigure()=0; protected: MaskFigure(); }; class MaskRound:public MaskFigure { public: MaskRound(); ~MaskRound(); }; class MaskRec:public MaskFigure { public: MaskRec(); ~MaskRec(); }; class MaskTri:public MaskFigure { public: MaskTri(); ~MaskTri(); }; #endif //mask.cpp #include <iostream> #include "mask.hpp" using std::cout; using std::endl; MaskFigure::MaskFigure() { } MaskFigure::~MaskFigure() { } MaskRound::MaskRound() { cout<<"Draw roundness on Mask"<<endl; } MaskRound::~MaskRound() { } MaskRec::MaskRec() { cout<<"Draw rectangle on Mask"<<endl; } MaskRec::~MaskRec() { } MaskTri::MaskTri() { cout<<"Draw triangle on Mask"<<endl; } MaskTri::~MaskTri() { } //factory.hpp #ifndef MASKFACTORY_HPP #define MASKFACTORY_HPP #include "mask.hpp" class FigureFactory { public: virtual ~FigureFactory()=0; virtual MaskFigure* CreateFigure()=0; protected: FigureFactory(); }; class RoundFactory:public FigureFactory { public: RoundFactory(); ~RoundFactory(); MaskRound* CreateFigure(); }; class RecFactory:public FigureFactory { public: RecFactory(); ~RecFactory(); MaskRec* CreateFigure(); }; class TriFactory:public FigureFactory { public: TriFactory(); ~TriFactory(); MaskTri* CreateFigure(); }; #endif //factory.cpp #include <iostream> #include "factory.hpp" using std::cout; using std::endl; FigureFactory::FigureFactory() { } FigureFactory::~FigureFactory() { } RoundFactory::RoundFactory() { cout<<"Init RoundFactory"<<endl; } RoundFactory::~RoundFactory() { } MaskRound* RoundFactory::CreateFigure() { return new MaskRound(); } RecFactory::RecFactory() { cout<<"Init RecFactory"<<endl; } RecFactory::~RecFactory() { } MaskRec* RecFactory::CreateFigure() { return new MaskRec(); } TriFactory::TriFactory() { cout<<"Init TriFactory"<<endl; } TriFactory::~TriFactory() { } MaskTri* TriFactory::CreateFigure() { return new MaskTri(); } //main.cc #include <memory> #include <iostream> #include "factory.hpp" #include "factorytml.hpp" using std::shared_ptr; int main() { shared_ptr<RoundFactory> roundfac(new RoundFactory()); shared_ptr<MaskRound> mrd(roundfac->CreateFigure()); shared_ptr<RecFactory> recfac(new RecFactory()); shared_ptr<MaskRec> mrc(recfac->CreateFigure()); shared_ptr<TriFactory> trifac(new TriFactory()); shared_ptr<MaskTri> mti(trifac->CreateFigure()); return 0; }
roundness, rectangle和 triangle的构造都分别延迟到了 RoundFactory, RecFactory和TriFactory等派生类中完成,因此factory method模式又被成为虚构造函数。
不难发现,MaskFigure有几个子类, FigureFactory也须要对应数目的子类,MaskFigure增长一个图形时,FigureFactory就必须增长相应的工厂方法,有时候会产生太多子类,不易维护,c++中能够引入模板或者参数化来解决,从而避免建立子类。一个模板实现的factory method实例以下:
//factorytml.hpp #ifndef FACTORYTML_HPP #define FACTORYTML_HPP #include <iostream> using std::cout; using std::endl; class FigureFactoryTml { public: FigureFactoryTml(){ cout<<"Init FigureFactoryTml"<<endl; } ~FigureFactoryTml(){ } template<typename T> T* CreateFigure() { return new T(); } }; #endif //main.cc … shared_ptr<FigureFactoryTml> fft(new FigureFactoryTml()); shared_ptr<MaskRound> mrdp(fft->CreateFigure<MaskRound>()); shared_ptr<MaskRec> mrcp(fft->CreateFigure<MaskRec>()); shared_ptr<MaskTri> mtip(fft->CreateFigure<MaskTri>()); …
(完)