首页 > 代码库 > 设计模式初识
设计模式初识
首先声明的是我对设计模式了解比较少,也才是刚刚接触,还有很多不懂的地方,这里写blog只是为了记录下看c++编程思想中的设计模式这一章,以便后续查看。
设计模式是国外4人合编的《Design Patterns》一书,这本书一般也被称为”四人帮”(Gangof Four, GoF)书。”四人帮”针对问题的特定类型提出了23中解决方案,即23个模式。定义为:每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题解决方案的核心。
当人们对某事物进行抽象的时候,隔离特定的细节,最直接的动机之一是为了使变化的事物与不变的事物分离开。它的目标是封装对象。
按照目的可以分为3类:1:创建性:包括单例模式、工厂模式及构建器模式。
2:结构性:有代理模式和适配器模式。3:行为性:其它模式。
信使:指将消息封装到一个对象中到处传递,而不是将消息的所有片段分开进行传递。
一:单例模式
单例模式是“四人帮”给出的最简单的设计模式,它是允许一个类有且仅有一个实例的方法。创建单例模式的关键是防止客户程序员获得任何控制其对象生存期的权利。
singleton.h
#ifndef SINGLETONPATTERN #define SINGLETONPATTERN class Singleton{ int i; Singleton(int x): i(x){} //声明为私有的,防止编译器隐式生成任何构造函数 Singleton& operator=(Singleton&); // 复制和赋值操作符被声明为私有的,以便防止任何这类复制动作的产生 Singleton(const Singleton&); public: static Singleton& instance(){ static Singleton s(47); return s; } int getValue(){return i;} void setValue(int x){i = x;} }; #endifMain
//1:单例模式 Singleton& s = Singleton::instance(); cout << s.getValue() << endl; s.setValue(11); Singleton& s2 = Singleton::instance(); cout << s2.getValue() << endl; s2.setValue(9); cout << s.getValue() << endl;
这里将静态对象放在一个函数中,延迟对对象的初始化,直到在该函数第1次被调用时才进行初始化。
注意:单例应该少用。真正的单例对象很少出现,而最终单例应该用于代替全局变量。
二:命令模式
命令模式是将函数封装为对象,就能够以参数的形式将其传递给其它对象或者函数,告诉它们在履行请求的过程中执行特定的操作。
commandPattern.h
#ifndef COMMANDPATTERN #define COMMANDPATTERN #include <iostream> #include <vector> using namespace std; class Command{ public: virtual void execute() = 0; }; class Hello:public Command{ public: void execute(){cout << "Hello ";} }; class World:public Command{ public: void execute(){cout << "World! ";} }; class IAM:public Command{ public: void execute(){cout << "I'm the command pattern!";} }; class Macro{ vector<Command*> commands; public: void add(Command* c){commands.push_back(c);} void run(){ vector<Command*>::iterator it = commands.begin(); while(it != commands.end()) { (*it++)->execute(); } } }; #endif
Main
//2:命令模式 Macro macro; macro.add(new Hello); macro.add(new World); macro.add(new IAM); macro.run();
三:代理模式和状态模式
代理模式(Proxy)和状态模式(State)都提供了一个代理类。代码和代理类打交道,而做实际工作的类隐藏在代理类的背后。当调用代理类的一个函数时,代理类仅转而去调用实现类中相应的函数。这两种模式很相似,从结构上看,可以认为代理模式是状态模式的一个特例。两者混在一起组成一个称为代理设计模式。
基本思想很简单:代理类派生自一个基类,由平行地派生自同一个基类的一个或者多个提供实际的实现。
区别:从结构上看:代理模式只有一个实现类,而状态模式有多个实现。可以认为两种模式的应用也不同:代理模式控制对其实现类的访问,而状态模式动态的改变其实现类。
代理模式:
proxyDemo.h
#ifndef PROXYDEMO #define PROXYDEMO #include <iostream> using namespace std; class ProxyBase{ public: virtual void f()=0; virtual void g()=0; virtual void h()=0; virtual ~ProxyBase(){} }; class Implementation:public ProxyBase{ public: void f(){cout << "Implementation.f()" << endl;} void g(){cout << "Implementation.g()" << endl;} void h(){cout << "Implementation.h()" << endl;} }; class Proxy:public ProxyBase{ ProxyBase *implementation; public: Proxy(){implementation = new Implementation();} ~Proxy(){delete implementation;} void f(){implementation->f();} void g(){implementation->g();} void h(){implementation->h();} }; #endifMain
//3:代理模式 Proxy p; p.f(); p.g(); p.h();
状态模式
stateCommand.h
#ifndef STATECOMMAND #define STATECOMMAND #include <iostream> using namespace std; class State{ public: virtual string response() = 0; }; class Frog:public State{ public: string response(){return "Ribbet!";} }; class Prince:public State{ public: string response(){return "Darling!";} }; class Creature{ // 代理类 State* state; public: Creature():state(new Frog()){} void greet(){ cout << state->response() << endl; } void kiss(){ delete state; state = new Prince(); } }; #endif
四:模板方法模式
模板方法模式是基类对象调用被子类覆盖的方法。即坚持相同的代码,覆盖不变的代码。
templateMethod.h
#ifndef TEMPLATEMETHOD #define TEMPLATEMETHOD class ApplicationFramework{ protected: virtual void customize1() = 0; virtual void customize2() = 0; public: void templateMethod(){ for(int i =0; i < 5; i++) { customize1(); customize2(); } } }; class MyApp:public ApplicationFramework{ private: void customize1(){cout << "Hello ";} void customize2(){cout << "World!" << endl;} }; #endif
Main
//模板方法模式 MyApp app; app.templateMethod();
五:策略模式
策略模式是在模板方法模式的基础上将不变的代码从“坚持相同的代码”中分开。
strategy.h
#ifndef STRATEGY #define STRATEGY #include <iostream> using namespace std; class NameStrategy{ public: virtual void greet() = 0; }; class SayHi:public NameStrategy{ public: void greet(){ cout << "Hi! How's it going?" << endl; } }; class Ignore:public NameStrategy{ public: void greet(){ cout << "Pretend I don't see you" << endl; } }; class Admission:public NameStrategy{ public: void greet(){ cout << "I'm Sorry, I forgot your name. " << endl; } }; class Context{ NameStrategy& strategy; public: Context(NameStrategy& strat):strategy(strat){} void greet(){strategy.greet();} }; #endifMain
// 策略模式 SayHi sayhi; Ignore ignore; Admission admission; Context c1(sayhi), c2(ignore), c3(admission); c1.greet(); c2.greet(); c3.greet();
六:职责链模式
职责链模式也许被看做一个使用策略对象的“递归的动态一般化”。此时提出一个调用,在一个链序列中的每个策略都试图满足这个调用。这个过程直到有一个策略成功满足该调用或者到达链序列的末尾才结束。由于职责链实际上就是一个链表,它能动态创建,因此可以看做是一个更一般的动态创建的switch语句。
chainOfResponsibility.h
#ifndef CHANIOFREPONSIBILITY #define CHANIOFREPONSIBILITY #include <iostream> #include <vector> using namespace std; enum Answer{NO, YES}; class GimmeStrategy{ public: virtual Answer canIHave() = 0; virtual ~GimmeStrategy(){} }; class AskMom:public GimmeStrategy{ public: Answer canIHave(){ cout << "Moom? can I have this?" << endl; return NO; } }; class AskDad:public GimmeStrategy{ public: Answer canIHave(){ cout << "Dad, I really need this!!" << endl; return NO; } }; class AskGrandpa:public GimmeStrategy{ public: Answer canIHave(){ cout << "Grandpa, is it my birthday yet?" << endl; return NO; } }; class AskGrandma:public GimmeStrategy{ public: Answer canIHave(){ cout << "Grandma, I really love you!!!" << endl; return YES; } }; class Gimme:public GimmeStrategy{ vector<GimmeStrategy*> chain; public: Gimme(){ chain.push_back(new AskMom()); chain.push_back(new AskDad()); chain.push_back(new AskGrandpa()); chain.push_back(new AskGrandma()); } Answer canIHave(){ vector<GimmeStrategy*>::iterator it = chain.begin(); while(it != chain.end()) if((*it++)->canIHave() == YES) return YES; cout << "Whiiiiinne!!" << endl; return NO; } ~Gimme(){ for(vector<GimmeStrategy*>::iterator iter = chain.begin(); iter!= chain.end(); iter++){ delete *iter; } } }; #endifMain
// 职责链模式 Gimme chain; chain.canIHave();
七:工厂模式—封装对象的创建
工厂模式就是将对象进行封装创建。强制用一个通用的工厂来创建对象。工厂模式可能是所有设计模式中最有用的模式之一。
1:静态工厂模式
将对象的创建封装到一个静态方法中即可。
shapeFactory.h
#ifndef SHAPEFACTORY #define SHAPEFACTORY #include <iostream> #include <stdexcept> #include <string> using namespace std; class Shape{ public: virtual void draw() = 0; virtual void erase() = 0; virtual ~Shape(){} class BadShapeCreation:public logic_error{ public: BadShapeCreation(const string &type):logic_error("cannot create type " + type){} }; static Shape* factory(const string& type) throw (BadShapeCreation); }; class Circle:public Shape{ Circle(){} // private constructor friend class Shape; public: void draw(){cout << "Circle::draw" << endl;} void erase(){cout << "Circle::erase" << endl;} ~Circle(){cout << "Circle::~Circle" << endl;} }; class Square:public Shape{ Square(){} friend class Shape; public: void draw(){cout << "Square::draw" << endl;} void erase(){cout << "Square::erase" << endl;} ~Square(){cout << "Square::~Square" << endl;} }; #endif
shapeFactory.cpp
#include "shapeFactory.h" Shape* Shape::factory(const string& type) throw (BadShapeCreation){ if(type == "Circle") return new Circle; if(type == "Square") return new Square; throw BadShapeCreation(type); }
Main
// 工厂模式---静态工厂方法 直接通过一个静态方法创建类的的对象(所有类 需要条件) char *s1[]={"Circle", "Square", "Square", "Circle", "Circle", "Circle", "Square"}; vector<Shape*> shapes; try{ for(size_t i = 0; i < sizeof(s1)/ sizeof(s1[0]); i++){ shapes.push_back(Shape::factory(s1[i])); } }catch(Shape::BadShapeCreation e){ cout << e.what()<< endl; purge(shapes.begin(), shapes.end()); return EXIT_FAILURE; } for(size_t i = 0; i < shapes.size(); i++){ shapes[i]->draw(); shapes[i]->erase(); } purge(shapes.begin(), shapes.end());
2:多态工厂
“四人帮”强调工厂方法模式的理由是,可以使不同类型的工厂派生自基类类型的工厂。静态工厂模式事实上是多态工厂模式的一个特例。
shapeFactory2.h
#ifndef SHAPEFACTORY2 #define SHAPEFACTORY2 #include <string> #include <stdexcept> #include <iostream> #include <algorithm> #include <map> using namespace std; class Shape{ public: virtual void draw() = 0; virtual void erase() = 0; virtual ~Shape(){} }; class ShapeFactory{ virtual Shape* create() = 0; static map<string, ShapeFactory*> factories; public: virtual ~ShapeFactory(){} friend class ShapeFactoryInitializer; // 内部类定义了一个异常 class BadShapeCreation:public logic_error{ public: BadShapeCreation(string type):logic_error("cannot create type " + type){} }; static Shape* createShape(const string& id) throw(BadShapeCreation); // 给定string找到它返回的shape类型 }; class Circle:public Shape{ Circle(){} friend class ShapeFactoryInitializer; class Factory; friend class Factory; class Factory:public ShapeFactory{ public: Shape* create(){return new Circle;} //friend class ShapeFactoryInitializer; }; public: void draw(){cout << "Circle::draw" << endl;} void erase(){cout << "Circle::erase" << endl;} ~Circle(){cout << "Circle::~Circle" << endl;} }; class Square:public Shape{ Square(){} class Factory; friend class Factory; friend class ShapeFactoryInitializer; class Factory:public ShapeFactory{ public: Shape* create(){return new Square;} //friend class ShapeFactoryInitializer; }; public: void draw(){cout << "Square::draw" << endl;} void erase(){cout << "Square::erase" << endl;} ~Square(){cout << "Square::~Square" << endl;} }; class ShapeFactoryInitializer{ // 对map数据结构进行了初始化 static ShapeFactoryInitializer si; ShapeFactoryInitializer(){ ShapeFactory::factories["Circle"] = new Circle::Factory; ShapeFactory::factories["Square"] = new Square::Factory; } ~ShapeFactoryInitializer(){ map<string, ShapeFactory*>::iterator it = ShapeFactory::factories.begin(); while(it != ShapeFactory::factories.end()) delete it++->second; } }; #endifshapeFactory2.cpp
#include "shapeFactory2.h" using namespace std; Shape* ShapeFactory::createShape(const string& id) throw(BadShapeCreation){ if(factories.find(id) != factories.end()) return factories[id]->create(); else throw BadShapeCreation(id); } map<string, ShapeFactory*>ShapeFactory::factories; ShapeFactoryInitializer ShapeFactoryInitializer::si;
Main
// 多态工厂----各种类型的工厂派生自基类的工厂 char *s1[] = {"Circle", "Square", "Square", "Circle", "Circle","Circle", "Square"}; vector<Shape*> shapes; try{ for(size_t i = 0; i < sizeof(s1)/sizeof(s1[0]); i++){ shapes.push_back(ShapeFactory::createShape(s1[i])); } }catch(ShapeFactory::BadShapeCreation e){ cout << e.what() << endl; purge(shapes.begin(), shapes.end()); return EXIT_FAILURE; } for(size_t i = 0; i < shapes.size(); i++){ shapes[i]->draw(); shapes[i]->erase(); } purge(shapes.begin(), shapes.end());
注意:如不需要创建独立的工厂对象,尽可能用静态工厂方法模式。
3:抽象工厂
它使用若干工厂方法模式。
abstractFactory.h
#ifndef ABSTRACTFACTORY #define ABSTRACTFACTORY #include <iostream> using namespace std; class Obstacle{ public: virtual void action() = 0; }; class Player{ public: virtual void interactWith(Obstacle*) = 0; }; class Kitty:public Player{ public: void interactWith(Obstacle* ob){ cout << "Kitty has encounted a "; ob->action(); } }; class KungFuGuy:public Player{ void interactWith(Obstacle* ob){ cout << "KungFuGuy now battles aganist a "; ob->action(); } }; class Puzzle:public Obstacle{ public: void action(){cout << "Puzzle" << endl;} }; class NastyWeapon:public Obstacle{ public: void action(){cout << "NastyWeapon" << endl;} }; class GameElementFactory{ public: virtual Player* makePlayer() = 0; virtual Obstacle* makeObstacle() = 0; }; class KittiesAndPuzzles:public GameElementFactory{ public: Player* makePlayer(){return new Kitty;} Obstacle* makeObstacle(){return new Puzzle;} }; class KillAndDismember:public GameElementFactory{ public: Player* makePlayer(){return new KungFuGuy;} Obstacle* makeObstacle(){return new NastyWeapon;} }; class GameEnvironment{ GameElementFactory* gef; Player* p; Obstacle* ob; public: GameEnvironment(GameElementFactory*factory):gef(factory), p(factory->makePlayer()), ob(factory->makeObstacle()){} void play(){p->interactWith(ob);} ~GameEnvironment(){ delete p; delete ob; delete gef; } }; #endif
Main
// 抽象工厂 GameEnvironment g1(new KittiesAndPuzzles), g2(new KillAndDismember); g1.play(); g2.play();
4:虚构造函数
虚构函数是使用一个“信封”类,信封类保存了一个指向基类对象的指针,“信封”类的构造函数决定采用什么样的特定类型。
其中基类扮演这派生类的代理的角色,而派生类提供行为中的变化。
virtualConstructor.h
#ifndef VIRTUALCONSTRUCTOR #define VIRTUALCONSTRUCTOR #include <iostream> #include <string> #include <stdexcept> using namespace std; class Shape{ Shape* s; Shape(Shape&); Shape operator=(Shape&); protected: Shape(){ s = 0; } public: virtual void draw(){s->draw();} virtual void erase(){s->erase();} virtual void test(){s->test();} virtual ~Shape(){ cout << "~Shape" << endl; if(s){ // 第二次调用的s为派生类继承的s 后面delete 0 不会有影响 cout << "Making virtual call:"; s->erase(); } cout << "delete s: "; delete s; } class BadShapeCreation:public logic_error{ public: BadShapeCreation(string type):logic_error("Cannot create type " + type){} }; Shape(string type) throw(BadShapeCreation); }; class Circle:public Shape{ Circle(Circle&); Circle operator=(Circle&); Circle():Shape(){} friend class Shape; public: void draw(){cout << "Circle::draw" << endl;} void erase(){cout << "Circle::erase" << endl;} void test(){draw();} ~Circle(){cout << "Circle::~Circle" << endl;} }; class Square:public Shape{ Square(Square&); Square operator=(Square&); Square(){} friend class Shape; public: void draw(){cout << "Square::draw" << endl;} void erase(){cout << "Square::erase" << endl;} void test(){draw();} ~Square(){cout << "Square::~Square" << endl;} }; #endif
virtualConstructor.cpp
#include "virtualConstructor.h" using namespace std; Shape::Shape(string type) throw(Shape::BadShapeCreation){ if(type == "Circle") s = new Circle; else if(type == "Square") s = new Square; else throw BadShapeCreation(type); draw(); }Main
// 虚构造函数 char *s1[] = {"Circle", "Square", "Square", "Circle", "Circle", "Circle","Square"}; vector<Shape*> shapes; cout << "virtual constructor calls:" << endl; try{ for(size_t i = 0; i < sizeof(s1)/sizeof(s1[0]); i++) shapes.push_back(new Shape(s1[i])); }catch(Shape::BadShapeCreation e){ cout << e.what() << endl; purge(shapes.begin(), shapes.end()); return EXIT_FAILURE; } for(size_t i = 0; i < shapes.size(); i++) { shapes[i]->draw(); cout << "test" << endl; shapes[i]->test(); cout << "end test" << endl; shapes[i]->erase(); } Shape c("Circle"); cout << "destructor calls:" << endl; purge(shapes.begin(), shapes.end());
注意:虚构造函数一般比较复杂,不建议使用。
以上便是个人暂时总结,后续再更新。
设计模式初识