设计模式
1、适配器Adapter(wrapper)模式
定义:
讲一个类的接口转换成客户希望使用的另外一个接口,解决两个接口之间不匹配的问题。Adatper模式
使得原本接口不兼容而不能一起工作的那些类可以一起工作。
角色:
- Target对象:负责定义所需要的方法,具体的业务需求(客户要求的)。
- Client请求者:负责使用Target角色定义的方法做具体处理。
- Adaptee适配器:一个持有既定方法的角色。
- Adapter适配器:Adapter模式的主人公,使用Adaptee的方法来满足Target的需求。
实现:
有两种方法:
①、类版本:可以方便地修改适配对象的部分行为(重载),但适配多个不同类型的功能时(多个接口或者需要多个类),实现比较复杂,而且
继承会带来意向不到的问题(比如Adaptee又有人添加了新的方法)。
②、对象版本:可以一次适配所有的子类,也建议用这一种方法。
对象实现代码:
1 #include<iostream> 2 using namespace std; 3 class Target 4 { 5 public: 6 Target(){} 7 virtual ~Target(){} 8 virtual void Request() 9 { 10 cout<<"Target::Request"<<endl; 11 } 12 }; 13 14 class Adaptee 15 { 16 public: 17 void SpecificRequest() 18 { 19 cout<<"Adaptee::SpecificRequest"<<endl; 20 } 21 }; 22 23 class Adapter : public Target 24 { 25 public: 26 Adapter() : m_Adaptee(new Adaptee) {} 27 28 ~Adapter() 29 { 30 if (m_Adaptee != NULL) 31 { 32 delete m_Adaptee; 33 m_Adaptee = NULL; 34 } 35 } 36 37 void Request() 38 { 39 m_Adaptee->SpecificRequest(); 40 } 41 42 private: 43 Adaptee *m_Adaptee; 44 }; 45 46 int main(int argc, char *argv[]) 47 { 48 Target *targetObj = new Adapter(); 49 targetObj->Request(); 50 51 delete targetObj; 52 targetObj = NULL; 53 54 return 0; 55 }
2、工厂模型设计
①、简单工厂模式。
通常就是一个工厂类XxxFactory,里面有一个静态方法,根据不同的参数,返回不同的派生自同一个父类(或同一个接口)的实例对象。
1 enum CTYPE {COREA, COREB}; 2 class SingleCore 3 { 4 public: 5 virtual void Show() = 0; 6 }; 7 //单核A 8 class SingleCoreA: public SingleCore 9 { 10 public: 11 void Show() { cout<<"SingleCore A"<<endl; } 12 }; 13 //单核B 14 class SingleCoreB: public SingleCore 15 { 16 public: 17 void Show() { cout<<"SingleCore B"<<endl; } 18 }; 19 //唯一的工厂,可以生产两种型号的处理器核,在内部判断 20 class Factory 21 { 22 public: 23 SingleCore* CreateSingleCore(enum CTYPE ctype) 24 { 25 if(ctype == COREA) //工厂内部判断 26 return new SingleCoreA(); //生产核A 27 else if(ctype == COREB) 28 return new SingleCoreB(); //生产核B 29 else 30 return NULL; 31 } 32 };
②、工厂方法模式。
之所以引入工厂方法模式,主要有两点:1、违背了开放封闭原则,软件实体(类、模板、函数)可以扩展,不可以修改。2、我们往往需要两个或者两个以上工厂。
1 class SingleCore 2 { 3 public: 4 virtual void Show() = 0; 5 }; 6 //单核A 7 class SingleCoreA: public SingleCore 8 { 9 public: 10 void Show() { cout<<"SingleCore A"<<endl; } 11 }; 12 //单核B 13 class SingleCoreB: public SingleCore 14 { 15 public: 16 void Show() { cout<<"SingleCore B"<<endl; } 17 }; 18 class Factory 19 { 20 public: 21 virtual SingleCore* CreateSingleCore() = 0; 22 }; 23 //生产A核的工厂 24 class FactoryA: public Factory 25 { 26 public: 27 SingleCoreA* CreateSingleCore() { return new SingleCoreA; } 28 }; 29 //生产B核的工厂 30 class FactoryB: public Factory 31 { 32 public: 33 SingleCoreB* CreateSingleCore() { return new SingleCoreB; } 34 };
③、抽象工厂模式。
当涉及到产品族的问题时候,比如又要生产多核处理器或者我们做手机(需要cpu工厂、主板工厂、os工厂、显示屏工厂),可以抽象一个做核工厂或者手机工厂。
1 //单核 2 class SingleCore 3 { 4 public: 5 virtual void Show() = 0; 6 }; 7 class SingleCoreA: public SingleCore 8 { 9 public: 10 void Show() { cout<<"Single Core A"<<endl; } 11 }; 12 class SingleCoreB :public SingleCore 13 { 14 public: 15 void Show() { cout<<"Single Core B"<<endl; } 16 }; 17 //多核 18 class MultiCore 19 { 20 public: 21 virtual void Show() = 0; 22 }; 23 class MultiCoreA : public MultiCore 24 { 25 public: 26 void Show() { cout<<"Multi Core A"<<endl; } 27 28 }; 29 class MultiCoreB : public MultiCore 30 { 31 public: 32 void Show() { cout<<"Multi Core B"<<endl; } 33 }; 34 //工厂 35 class CoreFactory 36 { 37 public: 38 virtual SingleCore* CreateSingleCore() = 0; 39 virtual MultiCore* CreateMultiCore() = 0; 40 }; 41 //工厂A,专门用来生产A型号的处理器 42 class FactoryA :public CoreFactory 43 { 44 public: 45 SingleCore* CreateSingleCore() { return new SingleCoreA(); } 46 MultiCore* CreateMultiCore() { return new MultiCoreA(); } 47 }; 48 //工厂B,专门用来生产B型号的处理器 49 class FactoryB : public CoreFactory 50 { 51 public: 52 SingleCore* CreateSingleCore() { return new SingleCoreB(); } 53 MultiCore* CreateMultiCore() { return new MultiCoreB(); } 54 };
3、组合模式(Composite)的设计 ,
定义:
Compose objects into tree strucgures to represent part-whole hierarchies.
Composite lets clients treat individual objects and compositions of objects uniformly.
要点:
1、组合模式让我们能用树形方式创建对象的结构,树里面包含了组合以及个别对象。
2、组合模式允许客户对个别对象(叶节点)以及组合对象一视同仁。
3、组合结构内的任意对象称为组件,组件可以是组合,也可以是叶节点。
4、页节点和组合必须实现相同的接口。
类图:
Component:组合中所有对象接口,不管是组合还是叶节点。
Leaf:叶节点。
Composite:组合,包含一个或多个孩子(可以是叶节点,也可以是组合)。
示例:
//MenuComponent.h文件 #ifndef __MENUCOMPONENT_H__ #define __MENUCOMPONENT_H__ namespace menu{ class MenuComponent{ public: class UnSupportedOp { }; MenuComponent() { } virtual ~MenuComponent() { } virtual void addMenuComponet(MenuComponent *m) { throw UnSupportedOp(); } virtual void print(int indent = 0) = 0; }; } #endif //MenuComposite.h文件 #ifndef __MENUCOMPOSITE_H__ #define __MENUCOMPOSITE_H__ #include<iostrem> #include<string> #include<vector> #include"MenuComponent.h" namespace menu{ using namesapce std; class MenuComposite:public MenuComponet { public: MenuComposite(string n):name(n) { } ~MenuComposite() { } void addMenuComponet(MenuComponent *m) { menuComponentVector.push_back(m); } void print(int indent) { for(int i=0;i < indent;i++){ cout << " "; } cout << name << "(Sub):" << endl; auto it = menuComponentVector.begin(); while(it != menuComponentVector.end()){ (*it)->print(indent+1); it++; } } private: //用vector保存组件 vector<MunuComponet *> menuComponentVector; string name; }; } #endif //menuitem.h文件 #ifndef __MENUTIEM_H_ #define __MENUTIEM_H_ #include<iostrem> #include<string> #include"MenuComponent.h" namespace menu{ using namesapce std; class MenuItem:public MenuComponet { public: MenuItem(string n,int p):name(n),price(p) { } ~MenuItem() { } void print(int indent) { for(int i=0;i < indent;i++){ cout << " "; } cout << name << ":" << price << endl; } private: string name; int price; }; }#endif
//main 文件
#include "MenuItem.h"
#include "MenuComposite.h"
using namespace menu;
int main()
{
MenuComponent *m = new MenuComposite("Diner");
m->addMenuComponet(new MenuItem("Meat",12));
m->addMenuComponet(new MenuItem("Fish",10));
MenuComponent *mm = new MenuComposite("Dessert");
mm->addMenuComponet(new MenuItem("Icecream",9));
m->addMenuComponet(mm);
m->print();
delete m;
delete mm;
return 0;
}
4、观察者模式。
观察者模式核心思想是1对多,
①、简单观察者模式。
1 //1、观察者接口 2 class ObserverInterface{ 3 public: 4 virtual void dosomething()=0; 5 virtual ~ObserverInterface(){} 6 }; 7 //2、被观察者接口 8 class SubjectInterface{ 9 public: 10 virtual void Add(ObserverInterface* obr)=0; 11 virtual void Remove(ObserverInterface* obr)=0; 12 virtual void Notify()=0; 13 14 virtual ~SubjectInterface(){} 15 }; 16 //3,我自己 17 class Me:public SubjectInterface{ 18 public: 19 void Add(ObserverInterface* obr) override{ 20 observers.push_back(obr); 21 } 22 23 void Remove(ObserverInterface* obr) override{ 24 auto pos=std::find(observers.begin(),observers.end(),obr); 25 if(pos!=observers.end()){ 26 observers.erase(pos); 27 } 28 } 29 30 void Notify() override{ 31 for(const auto& obs:observers){ 32 obs->dosomething(); 33 } 34 } 35 36 private: 37 std::vector<ObserverInterface*> observers; 38 };
5、单例模式的设计。
C++中的单例模式,保证一个类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。有很多地方需要这样的模块,
如系统的日志输出等。
按照C语言的风格,甚至可以直接使用一个全局变量做到这一点,但这样的代码显的很不优雅。《设计模式》一书中给出了一种不错的实现。
1 class CSingleton 2 { 3 public: 4 static CSingleton *GetInstane() 5 { 6 if(NULL == m_pInstance) 8 m_pInstance = new CSingleton(); 9 return m_pInstance; 11 } 12 private: 13 CSingleton() 14 { 15 } 16 static CSingleton *m_pInstance; 17 } 18 CSingleton* CSingleton::m_pInstance = NULL;//初始化静态变量
单例类CSingleton有以下特征:
1、它有一个指向唯一实例的静态指针m_pInstance,并且是私有的。
2、它有一个共有的函数,可以获取这个唯一的实例,并在需要的时候创建该
实例。
3、它的构造函数是私有的,这样就不能从别处创建该类的实例。
有经验的读者可能会问,m_pInstance指向的空间什么时候释放?更严重的问题是,这个实例的析构函数什么时候执行?如果在类中的析构行为中有必须的操作,比如关闭文件、释放外部资源
,上面的代码无法实现这个要求。我们需要一种方法,正常的删除该实例。
可以在程序结束时调用GetInstance并对返回的指针调用delete操作。这样做可以实现功能,但是不仅丑陋,而且容易出错,因为这样的附加代码很容易忘记,而且也很难保证在delete之后,没有代码
再调用GetInstance函数,一个妥善的方法是让这个类自己知道在合适的时候把自己删除。我们知道,程序在结束的时候,系统会自动析构所有的全局变量,事实上,系统也会析构所有类的静态成员变量。
利用这一个特征,我们可以在c++单例模式中定义这样一个静态成员变量,而它的唯一工作就是在析构函数中删除单例类的实例。如下面的代码中CGarbo类(Garbo意为垃圾工人)
1 class CSingleton: 2 { 3 // 其它成员 4 public: 5 static CSingleton * GetInstance() 6 { 7 if( NULL == m_pInstance) 8 m_pInstance = new CSingleton(); 9 return m_pInstance; 10 } 11 private: 12 CSingleton() 13 { 14 } 15 static CSingleton * m_pInstance; 16 class CGarbo // 它的唯一工作就是在析构函数中删除CSingleton的实例 17 { 18 public: 19 ~CGarbo() 20 { 21 if (CSingleton::m_pInstance) 22 delete CSingleton::m_pInstance; 23 } 24 }; 25 static CGarbo Garbo; // 定义一个静态成员,在程序结束时,系统会调用它的析构函数 26 } CSingleton* CSingleton::m_pInstance = NULL;//初始化静态变量 CSingleton::CGarbo CSingleton::CGarbo;//初始化静态变量
主要以下特征: 1、在单例内部定义专有的嵌套类,以防止该类在其他地方滥用。 2、在单例类内定义私有的专门用于释放的静态成员。 3、利用程序在结束时析构全局变量的特性,选择最终的释放时机。 4、使用c++单例模式的代码不需要任何操作,不必关系对象的释放。