https://github.com/iyjhabc/Design-Pattern
第一章:简单工厂模式
使用一个工厂类来根据参数调用不同的函数。因此增加功能时只需改变工厂类以及新增函数即可。
class oper { protected://使用保护成员,子类可以访问。子类不能访问私有成员 double lhs; double rhs; public: double virtual getResult()=0;//纯虚函数 void set_lhs(double lhs){this->lhs=lhs;} void set_rhs(double rhs){this->rhs=rhs;} }; class oper_add:public oper { public: double getResult(){ return lhs+rhs; } }; class oper_minus:public oper { public: double getResult(){ return lhs-rhs; } }; class factory { oper *op; public: factory(){op=NULL;} ~factory(){if(op)delete op;} oper* createOperator(char oper_char){ switch(oper_char){ case '+':op=new oper_add;break; case '-':op=new oper_minus;break; default:cout<<"operator error"<<endl; } return op; } }; //用户代码,计算器 double clientCounter(double lhs,double rhs,char oper_char){ factory fac; oper *op=fac.createOperator(oper_char); if(op==NULL)return 0; op->set_lhs(lhs); op->set_rhs(rhs); return op->getResult();//使用父类指针调用纯虚函数实现多态 }
第二章:策略模式
使用于对同一对象使用多种算法。而且算法经常需要修改或者替换。策略模式能使用户代码与算法隔离,修改算法代码不需要修改用户代码。
class Strategy { public: virtual double algorithm(double cash){//虚函数,用户实现多态 return cash; } }; class StrategyA:public Strategy { public: double algorithm(double cash){ return 0.8*cash;//八折 } }; class StrategyB:public Strategy { public: double algorithm(double cash){ return cash>=100?cash-30:cash;//满100减30 } }; class Context { Strategy *stra; public: void loadStrategy(Strategy *s){//加载算法 stra=s; } double getResult(double cash,int mode){ switch(mode){ case 0: this->loadStrategy(new StrategyA);break; case 1: this->loadStrategy(new StrategyB);break; default: this->loadStrategy(new Strategy); } return stra->algorithm(cash); } Context(){stra=NULL;} ~Context(){if(stra)delete stra;} }; //用户只需维护context类。如要增加算法,只需修改context类并给出新的算法类即可。 //用户接触不到算法,实现了算法与用户的隔离。修改算法的时候也无需修改用户代码 double clientFunction(double cash,int mode){ Context context; return context.getResult(cash,mode); }
第三章:单一职责原则
一个类只负责一个单一的职责,只能因为特定一种业务需该改变时才需要修改类。单一职责原则使代码耦合度降低,便于维护和复用。
第四章:开放-封闭原则
对扩展开放,对修改封闭。新增功能时,应该以添加新的类来实现,而不是修改原有代码。
第五章:依赖倒转原则(里氏代换原则)
抽象不应该依赖于细节,细节依赖于抽象。针对接口与抽象类编程,而不是针对实现编程。
依赖翻转原则实现的基础:里氏代换原则-如果父类都替换成它的子类,软件不会有任何问题。例如猫狗养猪都抽象于动物类,当我们的对象从猫换成狗时,由于他们符合里氏代换原则,其他代码不必修改。
第六章:装饰模式
装饰模式能够为对象动态地、有序地新增一些功能。用户代码可以自主地新增功能(用户关心的是以什么顺序增添什么新功能,并不是功能的具体实现),新增功能时只需添加新的装饰实体类即可,分离了用户的核心功能与个别的装饰功能,而且每种装饰也容易复用。
class Component { public: virtual void operation()=0; }; //具体的对象 class ConcreteComponent:public Component { public: void operation(){cout<<"I am a man"<<endl;} }; //装饰类 class Decorator:public Component { protected: Component *comp; public: Decorator(){comp=NULL;} ~Decorator(){if(comp)delete comp;} void set_component(Component *comp){ this->comp=comp; } void operation(){ if(comp)comp->operation();//关键,运行set_component所设置的行为 } }; //具体装饰类A,穿衣服 class ConcreteDecoratorA:public Decorator { public: void operation(){ Decorator::operation();//执行之前的装饰 cout<<"dress clothes"<<endl;//本装饰类自有的行动 } }; //具体装饰类B,穿裤子 class ConcreteDecoratorB:public Decorator { public: void operation(){ Decorator::operation();//执行之前的装饰 cout<<"dress trousers"<<endl;//本装饰类自有的行动 } }; //客户端代码,穿着函数 void clientDress(){ ConcreteComponent man; ConcreteDecoratorA *decA=new ConcreteDecoratorA; ConcreteDecoratorB *decB=new ConcreteDecoratorB; decA->set_component(&man);//decA父类的comp设置成了man,operation为man的行为 decB->set_component(decA);//decB父类的conp设置成了decA,operation为decA的行为 decB->operation();//先运行祖先decA的operation,而A的operation则先要运行祖先man的。 delete decA;//因此先man->opertion,再A->opertion,再B->opertion delete decB;//其实就是通过set_component每层改变comp为不同的实体装饰 }
第七章:代理模式
设计模式中定义: 为其他对象提供一种代理以控制对这个对象的访问(提供一个壳)。
1) 远程代理(Remote Proxy)为一个位于不同的地址空间的对象提供一个本地的代理对象。例如网站加载大图片时可先加载包含图片位置与尺寸的代理,网站顺利显示后再下载大图片,增加网站响应速度。
2) 虚拟代理(Virtual Proxy)根据需要创建开销很大的对象。如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的代理对象来表示,真实对象只在需要时才会被真正创建。延迟创建真实的消耗大的对象提高系统系敖律。
3) 保护代理(Protection Proxy)控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。
4) 智能指引(Smart Reference)取代了简单的指针,它在访问对象时执行一些附加操作。
代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。
//抽象父类 class Subject { public: void virtual request()=0; }; //真实对象类 class Real_subject:public Subject { public: void request(){ cout<<"my real request"<<endl; } }; //代理类 class Proxy:public Subject { Real_subject *subject; public: void request(){ if(subject==NULL)subject=new Real_subject;//延迟创建Realsubject,用时才创建 cout<<"I am a proxy"<<endl;//通过代理可以添加或屏蔽真实对象的功能 subject->request(); } Proxy(){subject=NULL;} ~Proxy(){if(subject)delete subject;} }; //客户端代码 void dosomething(Subject &subject){ subject.request(); } int main(){ Proxy proxy; dosomething(proxy); return 0; }
第八章:工厂方法模式
与简单工厂模式的区别是,工厂变成一个抽象类,各种功能再独自继承功能工厂类。工厂类不再判断需要返回什么功能类指针,这个判断交给客户代码。如此一来新增功能时,只需增加新的方法子类,新工厂子类以及修改客户代码,不需像简单工厂模式那样修改工厂类的代码,更加符合开放-封闭原则。
代码跟简单工厂差不多:https://github.com/iyjhabc/Design-Pattern/blob/master/factory_mothod_pattern.cpp
第九章:原型模式
原型模式提供了一个浅复制的克隆接口,继承接口的子类可以把原型的当前状态复制到克隆体
优点:1、克隆直接复制内存,不调用构造函数,可以快速克隆初始化开销巨大的对象;2、由于直接复制内存,克隆体跟原型的当前状态完全一致,因此可以动态地根据需要克隆,而不是新建一个初始状态的对象。
注意:克隆提供的是浅复制,就是引用指针这种变量只是把地址直接复制到克隆体,他们指向的对象还是原型所指向的。
//可克隆抽象父类 class Prototype { public: virtual Prototype* clone()=0; static void freeClone(Prototype *pclone){ delete pclone; } }; //实际类,如简历类 class resume:public Prototype { string name; int &age;//引用类型声明时必须初始化,因此必须使用初始化列表 string experience; public: resume(string name,int &age,string experience):name(name),age(age),experience(experience){} void set_age(int new_age){ this->age=new_age; } void display(){ cout<<this->age<<endl<<this->name<<endl<<this->experience<<endl; } Prototype* clone(){//实现深复制的话只能另外new一个resume对象 //因为resume有引用成员变量,引用被初始化以后就不能改变引用目标 resume *presume=(resume*)malloc(sizeof(resume));//直接浅复制,不必调用构造函数 memcpy(presume,this,sizeof(resume));//也无视访问权限 return presume; } }; int main(){ int age=25; resume resumeA("yjh",age,"student"); resumeA.display(); resumeA.display(); resumeA.set_age(26);//动态复制,克隆的结果为最新的值 resume *resumeB=(resume*)resumeA.clone(); resumeB->display(); resumeB->set_age(17);//改变B的age也是也改变了A的 resumeB->display(); resumeA.display();//age=17,浅复制,只复制了地址,克隆体的引用类型还是引用了原型的 Prototype::freeClone(resumeB); return 0; }
第十章:模板模式
声明一个模板抽象类,把固定的操作写入模板函数中。把以后可能改变的部分声明为虚函数,让子类实现,达到代码复用。
//抽象模板类 class Template { public: virtual void altertableOperation1()=0;//模板中的可变操作部分 virtual void altertableOperation2()=0; void fixOperation1(){cout<<"fixOperation1 has done"<<endl;} void fixOperation2(){cout<<"fixOperation2 has done"<<endl;} void templateMethod(){ fixOperation1(); altertableOperation1();//填空,把以后需要改变的地方声明为虚函数 fixOperation2(); altertableOperation2(); } }; //实际应用模板类A class concreteClassA:public Template { public: void altertableOperation1(){ cout<<"classA op1 has done"<<endl; } void altertableOperation2(){ cout<<"classA op2 has done"<<endl; } }; //实际应用模板类B class concreteClassB:public Template { public: void altertableOperation1(){ cout<<"classB op1 has done"<<endl; } void altertableOperation2(){ cout<<"classB op2 has done"<<endl; } }; //用户代码 void client(){ Template *p=new concreteClassA; p->templateMethod(); }
第十二章:外观模式
给同一类子类提供一个简单的、公共的父类,组合子类的方法(如外观接口的methodA是子类1、2、4方法的叠加),给用户提供接口。用户只需知道外观接口,不必接触里面复杂的细节,使代码便于维护,降低类之间的耦合。
第十三章:建造者模式
用于创建一些复杂的对象,对象内部的建造顺序通常是稳定的,但内部构建通常面临着复杂的变化。因此使用构造者来隔离用户与建造过程,并且使用必须重写的纯虚函数来规定每个产品的生产步骤,而细节必须被重新定制。
class Product { string partA; string partB; public: void set_partA(string partA){ this->partA=partA; } void set_partB(string partB){ this->partB=partB; } void show_product(){ cout<<partA<<" "<<partB<<endl; } }; class Builder { public: virtual void set_partA()=0; virtual void set_partB()=0; virtual Product* get_product()=0; }; class ProductBuilderA:public Builder { Product *product; void set_partA(){//必须重写的纯虚函数 product->set_partA("xx");//私有的,必须利用get_product调用 } void set_partB(){//确保产品必须被定制 product->set_partB("yy"); } public: ProductBuilderA(){ product=new Product; } Product*get_product(){//修改此函数可以改变定制 set_partA();//书中还通过一个director来完成定制,但我感觉集成到这里就可以了 set_partB(); return product; } }; void client(){ Builder *builder=new ProductBuilderA; Product *A=builder->get_product(); A->show_product(); delete builder; delete A; }
第十四章:观察者模式
观察者模式用于一个类与多个类紧密相关,一个类的状态改变了,多个类的状态也要协同改变。使用观察者模式可以把多类之间的关联解耦。使得设计更符合依赖翻转原则,即依赖于抽象。
class Observer { public: virtual void update()=0; }; class Subject//用户可以继承Subject来表达自己的主题 { int state; list<Observer*> observer_list; public: void set_state(int new_state){ this->state=new_state; } int get_state(){ return this->state; } void add_observer(Observer* observer){ observer_list.push_back(observer); } void del_observer(Observer* observer){ observer_list.erase(find(observer_list.begin(),observer_list.end(),observer)); } void notify(){ for(list<Observer*>::iterator it=observer_list.begin();it!=observer_list.end();++it){ (*it)->update();//由subject统一更新observer } } }; class concreteObserverA:public Observer { public: void update(){ cout<<"concreteObserverA is updated"<<endl; } }; class concreteObserverB:public Observer { public: void update(){ cout<<"concreteObserverB is updated"<<endl; } }; void client(){ Observer *observerA=new concreteObserverA; Observer *observerB=new concreteObserverB; Subject *subject=new Subject; subject->add_observer(observerA); subject->add_observer(observerB); subject->set_state(1); if(subject->get_state()){//如果状态改变了,所有的observer需要协同改变 subject->notify(); } delete observerA; delete observerB; delete subject; }