设计模式

参考:
《大话设计模式》
爱编程的大丙

设计原则#

  1. 单一职责原则:每个类应仅仅负责一种功能逻辑
  2. 开放封闭原则:对原有的代码封闭,不能修改。对新的功能开放,可以扩展。在设计时,尽量抽象出以后不会改变的类,之后有新的改动可以通过增加新代码,而不改变原有类的方法实现。比如在客户端类中实现四则运算,每增加一种运算就要修改类,可以将运算中不变的抽象出来,之后每增加新的运算,在此基础上扩展就好。
  3. 依赖倒转原则:抽象不依赖细节,细节依赖抽象。高层模块与底层模块不应该相互依赖,应该都依赖与一个接口(c++就是抽象类),实现各模块的主要目标是实现这个接口。
  4. 迪米特(最少知识)原则:每个类应尽量减少自己成员和方法的访问权限。两个类如果不直接通信就不应直接相互作用,如果需要调用另一个类的方法,应该通过第三方调用
  5. 合成聚合原则:优先使用合成聚合,尽量不要使用类继承
  6. 里氏代换原则:子类型必须能替换父类型

创建型模式#

简单工厂模式#

当实例化不同对象,且经常变化时,考虑使用。但是不满足开放封闭原则。
一个抽象运算类,加减乘除四个运算类继承这个抽象类,运算工厂类依赖于抽象运算类,负责根据输入的符号构造具体的四个运算类
img

Copy
#include<iostream> class Operator { public: virtual int GetResult() { return 0; } int a=0; int b=0; }; class AddOperator :public Operator { int GetResult() override { return a + b; } }; class SubOperator :public Operator { int GetResult() override { return a - b; } }; class MulOperator :public Operator { int GetResult() override { return a * b; } }; class DivideOperator :public Operator { int GetResult() override { if (b != 0) { return a / b; } else { throw "除数不能为零"; } } }; class OperatorFactory { public: static Operator* Createoperator(char sign) { Operator *oper=nullptr; switch (sign) { case '+': oper = new AddOperator(); break; case '-': oper = new SubOperator(); break; case '*': oper = new MulOperator(); break; case '/': oper = new DivideOperator(); break; } return oper; } }; int main() { Operator *oper = OperatorFactory::Createoperator('/'); oper->a = 6; oper->b = 3; int r = oper->GetResult(); std::cout << r; }

工厂模式#

简单工厂模式需要修改工厂类,违反开放封闭原则。工厂模式为工厂类抽象一个接口,其子类来分别实现接口,这样运算类与工厂类就互不依赖
img

Copy
#include<iostream> class Operator { public: virtual int GetResult() { return 0; } int a = 0; int b = 0; }; class AddOperator :public Operator { int GetResult() override { return a + b; } }; class SubOperator :public Operator { int GetResult() override { return a - b; } }; class MulOperator :public Operator { int GetResult() override { return a * b; } }; class DivideOperator :public Operator { int GetResult() override { if (b != 0) { return a / b; } else { throw "除数不能为零"; } } }; class OperatorFactory { public: virtual Operator* Createoperator()=0; }; class AddFactory : public OperatorFactory { public: Operator* Createoperator() override { return new AddOperator(); } }; class SubFactory : public OperatorFactory { public: Operator* Createoperator() override { return new SubOperator(); } }; class MulFactory : public OperatorFactory { public: Operator* Createoperator() override { return new MulOperator(); } }; class DivideFactory : public OperatorFactory { public: Operator* Createoperator() override { return new DivideOperator(); } }; int main() { OperatorFactory* factory = new DivideFactory(); Operator *oper= factory->Createoperator(); oper->a = 6; oper->b = 3; int r = oper->GetResult(); std::cout << r; }

抽象工厂模式#

当工厂模式中的要生成类的种类很多时,可以使用抽象模式进一步改造,本质是对它们进行分类。
比如下面例子中要产生MYSQL插入用户数据的类,向MYSQL插入水果数据的类,向SQLserver插入用户数据的类,向SQLserver插入水果数据的类。可以分为向MYSQL和SQLserver插入数据的类,再在两个类中生成插入用户数据和水果数据的类。
这里没有画出用户类,水果类的关系
img

Copy
#include<iostream> using namespace std; class User { public: string name; int age; User(string name, int age) :name(name), age(age) {}; }; class UserInterface { public: virtual void insert(User* user) = 0; }; class SQLServerUser :public UserInterface { public: void insert(User* user) override { cout << "实现向SQLserver的user表中插入数据" << user->name<<" " << user->age << "\n"; } }; class MYSQLUser :public UserInterface { public: void insert(User* user) override { cout << "实现向MYSQL的user表中插入数据" << user->name << " " << user->age << "\n"; } }; class Fruit { public: string name; int price; Fruit(string name, int price) :name(name), price(price) {}; }; class FruitInterface { public: virtual void insert(Fruit fruit) = 0; }; class SQLServerFruit :public FruitInterface { public: void insert(Fruit fruit) override { cout << "实现向SQLserver的fruit表中插入数据" << fruit.name << " " << fruit.price << "\n"; } }; class MYSQLFruit :public FruitInterface { public: void insert(Fruit fruit) override { cout << "实现向MYSQL的fruit表中插入数据" << fruit.name << " " << fruit.price << "\n"; } }; class FactoryInterface { public: virtual UserInterface* CreateUser() = 0; virtual FruitInterface* CreateFruit() = 0; }; class SQLserverFactory :FactoryInterface { public: static UserInterface* CreaterUser() { return new SQLServerUser(); } static FruitInterface* CreteFruit() { return new SQLServerFruit(); } }; class MYSQLFactory :FactoryInterface { public: static UserInterface* CreaterUser() { return new MYSQLUser(); } static FruitInterface* CreteFruit() { return new MYSQLFruit(); } }; int main() { //UserInterface* user = SQLserverFactory::CreaterUser(); UserInterface* user = MYSQLFactory::CreaterUser(); user->insert(new User("小明",16)); }

但是每增加一种具体的需求,需要增加多个类,可以使用简单工厂来改进抽象工厂。之后还可以利用反射进一步改进。

Copy
#include<iostream> #include<vector> using namespace std; class User { public: string name; int age; User(string name, int age) :name(name), age(age) {}; }; class UserInterface { public: virtual void insert(User* user) = 0; }; class SQLServerUser :public UserInterface { public: void insert(User* user) override { cout << "实现向SQLserver的user表中插入数据" << user->name<<" " << user->age << "\n"; } }; class MYSQLUser :public UserInterface { public: void insert(User* user) override { cout << "实现向MYSQL的user表中插入数据" << user->name << " " << user->age << "\n"; } }; class Fruit { public: string name; int price; Fruit(string name, int price) :name(name), price(price) {}; }; class FruitInterface { public: virtual void insert(Fruit fruit) = 0; }; class SQLServerFruit :public FruitInterface { public: void insert(Fruit fruit) override { cout << "实现向SQLserver的fruit表中插入数据" << fruit.name << " " << fruit.price << "\n"; } }; class MYSQLFruit :public FruitInterface { public: void insert(Fruit fruit) override { cout << "实现向MYSQL的fruit表中插入数据" << fruit.name << " " << fruit.price << "\n"; } }; class DataAccess { public: const static int database=0;//0 sqlserver,1 mysql static UserInterface* CreaterUser() { UserInterface* instance=nullptr; switch (database) { case 0: instance=new SQLServerUser(); case 1: instance=new MYSQLUser(); } return instance; } static FruitInterface* CreteFruit() { FruitInterface* instance = nullptr; switch (database) { case 0: instance = new SQLServerFruit(); case 1: instance = new MYSQLFruit(); } return instance; } }; int main() { UserInterface* user =DataAccess::CreaterUser(); user->insert(new User("小明",16)); }

建造者模式#

当对象构建过程稳定,但内部细节可能变化时使用。使得对象构建与表示分离,只需要指定构造类型就可以创建不同的表示
主要包含产品类(产品有不同的表现),建造者(负责为构造产品提供一组抽象接口),具体构造者(实现抽象接口),指导者(构建使用建造者接口的对象)
img

Copy
#include<iostream> #include<vector> using namespace std; //产品类 class Soup { public: vector<string> ingredients; void Add(string in) { cout << "加了点" << in << '\n'; ingredients.push_back(in); } void Show() { cout << "这个汤的配料有" << '\n'; for (auto i = ingredients.begin(); i != ingredients.end(); ++i) { cout << *i << " "; } } }; //构造者 class CookSoup { public: virtual void AddVegetable() = 0; virtual void AddWater() = 0; virtual void AddSeasoning() = 0; }; //具体构造者 class CookTomotoSoup :public CookSoup { public: Soup* soup; CookTomotoSoup(Soup* soup) { this->soup = soup; } void AddVegetable() { soup->Add("西红柿"); } void AddWater() { soup->Add("水"); } void AddSeasoning() { soup->Add("盐"); } Soup *Get() { return soup; } }; //指导者 class Director { public: void cook(CookSoup* cooksoup) { cooksoup->AddWater(); cooksoup->AddVegetable(); cooksoup->AddSeasoning(); } }; int main() { Director* d = new Director(); Soup *soup = new Soup(); CookTomotoSoup* s = new CookTomotoSoup(soup); d->cook(s); Soup *dish = s->Get(); dish->Show(); }

原型模式#

不通过构造函数,用一个对象初始化另一个对象。实现方法是在原型类中声明克隆自己的接口(c++中就是虚函数),在具体实现类中实现这一接口。

主要是为了多态,使用父类指针克隆子类

Copy
#include<iostream> using namespace std; class WorkExperience { public: string company; }; class Resume { protected: string name; int age; WorkExperience workExperience; public: virtual void display() = 0; virtual Resume* clone() = 0; }; class ConcreteResume1:public Resume { public: ConcreteResume1(string name, int age,string company) { this->name = name; this->age = age; this->workExperience.company = company; } ConcreteResume1(ConcreteResume1& resume) { this->name = resume.name; this->age = resume.age; } void setName(string name) { this->name = name; } void setAge(int age) { this->age = age; } void setWorkExperience(string company) { this->workExperience.company = company; } void display() override { cout << "姓名" << name << "年龄" << age << workExperience.company<< '\n'; } ConcreteResume1* clone() override { return new ConcreteResume1(*this); } }; int main() { Resume *resume1 = new ConcreteResume1("小华", 20,"大米"); ConcreteResume1 *resume3 = resume1.clone(); resume3->display(); }

单例模式#

当某个类只能实例化一个对象时使用

所有拷贝构造函数要delete掉
默认构造函数要设为private
使用静态变量保存实例化的对象,并提供函数返回这个对象

根据对象实例化时机的不同分为
懒汉模式:只有在使用时才实例化对象
饿汉模式:代码初始化时就实例化对象

结构性模式#

适配器模式#

主要用于补救,当不容易直接修改代码时,来统一调用的接口,STL中就有适配器
img

Copy
//假设这里只支持out,不支持SpecialOut #include<iostream> using namespace std; class Normal { public: static void out() { cout << "通用的输出" << '\n'; } }; class Special { public: static void SpecialOut() { cout << "特别的输出" << '\n'; } }; class Adapte :public Normal { public: static void out(Special *special) { special->SpecialOut(); } }; int main() { //假设这里只支持out Normal::out(); Adapte::out(new Special()); }

代理模式#

代替一个对象对另一个对象访问,用在:

  • 远程代理
  • 虚拟代理:当需要创建开销很大的对象时,通过代理存放对象,来逐步创建
  • 安全代理:控制访问权限
  • 智能指引:在调用对象时,处理一些额外的事

相比适配器模式:都是在原来之上加了一层。适配器模式是原接口不能使用,转换为能使用的新接口,代理模式是和原接口一样,只是想隐藏原接口,并且通过代理可以额外做其它的事。
这里省略了target类的关系
img

Copy
#include<iostream> #include<fstream> using namespace std; class GiveInterface { public: virtual void Givemoney()=0; virtual void GiveGift() = 0; }; class Target { public: string name; Target(string name) :name(name) {}; }; class Pursuit :public GiveInterface { public: Target *person; string myname; Pursuit(Target* person,string myname) { this->person = person; this->myname = myname; } void Givemoney() { cout << "送钱给" <<person->name<< '\n'; } void GiveGift() { cout << "送礼物给" << person->name << '\n'; } }; class Proxy :public GiveInterface { public: Pursuit *pursuit; Proxy(Target* person,string client) { this->pursuit = new Pursuit(person,client); } void Givemoney() { cout << "代表" << pursuit->myname << ","; pursuit->Givemoney(); } void GiveGift() { cout << "代表" << pursuit->myname << ","; pursuit->GiveGift(); } }; int main() { Target t("花花"); string client = "李华"; Proxy p(&t,client); p.GiveGift(); p.Givemoney(); } 代表李华,送礼物给花花 代表李华,送钱给花花

外观(门面)模式#

为子系统一组接口,提供一个统一的高层接口

  • 在设计初期,在数据访问和业务逻辑和表示层各层之间建立这样的类
  • 在维护复杂老系统时建立这样的类来提供更清晰的接口

与代理的区别是:代理只代表一个对象,而这个对象不允许直接被访问。外观是代表一个系统,通过外观对象访问子系统各个对象
下面例子的子系统包含door类和people类两个类,在之上提供一个更高层的GoHome类
img

Copy
#include<iostream> using namespace std; class Door { public: void open() { cout << "开门" << '\n'; } void close() { cout << "关门" << '\n'; } }; class People { public: void walk() { cout << "走……" << '\n'; } }; class GoHome { public: Door *door; People *people; GoHome() { door = new Door(); people = new People(); } void start() { door->open(); people->walk(); door->close(); } }; int main() { GoHome* gohome = new GoHome(); gohome->start(); }

桥接模式#

当实现可以有多角度去分类时,只用继承会增加大量类,这时用桥接模式:让多角度的类独立出来,使得每种类的变化不会影响到其它类。
如下例,不同手机有不同的APP,比如只靠继承,手机品牌1要实现手机品牌1的游戏app,社交app,手机品牌2要实现手机品牌1的游戏app,社交app会产生多个类。
用桥接分别实现手机品牌类和APP类,再通过手机聚合APP,像桥一样接起来。
img

Copy
#include<iostream> #include<vector> using namespace std; class APP { public: virtual void RUN() = 0; }; class GameAPP:public APP { public: void RUN() { cout << "游戏启动" << '\n'; } }; class SocialAPP :public APP { public: void RUN() { cout << "社交应用启动" << '\n'; } }; class Phone { public: vector<APP*> app; virtual void RUN(int appID)=0; }; class MIPhone:public Phone { public: void RUN(int appID) override { app[appID]->RUN(); } }; int main() { MIPhone *phone = new MIPhone(); phone->app.push_back(new SocialAPP()); phone->app.push_back(new GameAPP()); phone->RUN(0); }

装饰模式#

可以有选择和有顺序的为已有功能动态添加更多功能,比生成子类更灵活
当需要满足类一些特殊功能时,不增加原有类的复杂度,而把功能封装为一个类,用这个功能类包装需要修饰的对象。
下例中Todo类装饰Myday,继承它原有的功能,并增加其它功能
img

Copy
#include<iostream> class Myday { public: std::string date; Myday(){} Myday(std::string date) { this->date = date; } virtual void ShowMyLife() { std::cout << date << "我的生活记录"<< '\n'; } }; class Todo:public Myday { public: Myday *myday; void doThing(Myday *myday) { this->myday = myday; } void ShowMyLife() { myday->ShowMyLife(); } }; class ToSleep :public Todo { public: void ShowMyLife() override { Todo::ShowMyLife(); std::cout << "睡了一觉" << '\n'; } }; class ToEat :public Todo { public: void ShowMyLife() override { Todo::ShowMyLife(); std::cout << "吃了一顿" << '\n'; } }; int main() { Myday i("7月23日"); ToSleep *sleep = new ToSleep(); ToEat* eat = new ToEat(); eat->doThing(&i); sleep->doThing(eat); sleep->ShowMyLife(); }

享元模式#

当需要创建多个对象,而这些对象又有很多相同的参数,可以通过享元模式,只用实例化几个对象,而把不同的参数保存在外部的对象中,这样可以节省内存等开销。
比如有不同网站类型,但同一网站只有用户有区别,可以把用户单独出来,相同类型网站都是相同的,只要指定不同的用户
img

Copy
#include<iostream> #include<map> using namespace std; class User { public: string name; User(string name) :name(name) {}; }; class WebSite { public: virtual void Use(User user) = 0; }; class ConcreteWebSite :public WebSite { public: string type; ConcreteWebSite(string type):type(type){} void Use(User user) override { cout << "关于" << type << "设置使用。"; cout << user.name << "使用"<<'\n'; } }; class WebSiteFactory { public: map<string, ConcreteWebSite*> factory; ConcreteWebSite* GetWebSIte(string type) { if(factory.find(type)==factory.end()) { factory.insert({ type,new ConcreteWebSite(type) }); } return factory[type]; } }; int main() { //user相当于外部信息 User user1("小明"); User user2("小红"); User user3("小王"); //下面只用实例化两个对象,小明和小红共用一个电子商城 WebSiteFactory *webFactory = new WebSiteFactory(); ConcreteWebSite *web1=webFactory->GetWebSIte("电子商城"); web1->Use(user1); ConcreteWebSite* web2 = webFactory->GetWebSIte("电子商城"); web2->Use(user2); ConcreteWebSite* web3 = webFactory->GetWebSIte("视频网站"); web3->Use(user3); }

组合模式#

用于对象具有树形层次结构时
img

Copy
#include<iostream> #include<list> using namespace std; class Component { public: string name; Component(string name) :name(name) {}; virtual void add(Component* component) = 0; virtual void remove(Component* component) = 0; virtual void display() = 0; }; class Leaf: public Component { public: Leaf(string name) :Component(name) {}; void add(Component* component) { cout << "叶结点没有子节点" << '\n'; } void remove(Component* component) { cout<< "叶结点没有子节点" << '\n'; } void display() { cout << this->name << '\n'; } }; class Twigs :public Component { public: Twigs(string name) :Component(name) {}; list<Component*> child; void add(Component* component) { child.push_back(component); } void remove(Component* component) { child.remove(component); } void display() { cout << this->name << '\n'; for (auto i=child.begin();i!=child.end();++i) { (*i)->display(); } } }; int main() { Twigs root("根节点0"); Twigs child1("子节点1"); Leaf child2("叶节点2"); Leaf child3("叶节点3"); Leaf child4("叶节点4"); child1.add(&child3); child1.add(&child4); root.add(&child1); root.add(&child2); root.display(); child1.remove(&child4); root.display(); }

行为模式#

观察者模式#

当一种对象变化时,需要改变其它对象的状态时使用。
其它对象监听某种改变(其实就是定义一个通知自己的函数),当有改变时该对象调用这个函数。
但实际中多种类通知自己的接口都不统一,所以有委托的特性(在C#等中)。
下例中,每个学生子类都定义了Notify函数,监视者类是老师的子类,当其状态变为“老师来了”,他就调用学生对象的Notify函数通知学生
img

Copy
#include<iostream> #include<vector> using namespace std; class Student { public: string name; string state; virtual void Notify() {}; }; class TalkStudent :public Student { public: TalkStudent(string name) { this->name = name; this->state = "侃侃而谈"; } void StopTalk() { cout << this->name << "停止说话" << '\n'; } virtual void Notify() override { this->StopTalk(); this->state = "认真学习"; cout << this->name << this->state << '\n'; } }; class PlayStudent :public Student { public: PlayStudent(string name) { this->name = name; this->state = "愉快玩耍"; } void StopPlay() { cout << this->name << "停止玩耍" << '\n'; } void Notify() override { this->StopPlay(); this->state = "认真学习"; cout << this->name << this->state << '\n'; } }; class TeacherSubject { public: string state; vector<Student*> *students; virtual void Add(Student* student) = 0; virtual void Remove(Student* student) = 0; virtual void Notify() = 0; }; class MonitorTeacher :public TeacherSubject { public: MonitorTeacher() { this->students = new vector<Student*>(); } void Add(Student* student) override { students->push_back(student); } void Remove(Student* student) override { for (auto i = students->begin(); i != students->end(); ++i) { if ((*i)->name == student->name) { students->erase(i); } } } void Notify() override { cout << this->state << '\n'; for (auto i = students->begin(); i != students->end(); ++i) { (*i)->Notify(); } } }; int main() { TalkStudent* tStudent = new TalkStudent("小明"); PlayStudent* pStudent = new PlayStudent("小王"); MonitorTeacher *monitor = new MonitorTeacher(); monitor->Add(tStudent); monitor->Add(pStudent); monitor->state = "老师来了"; monitor->Notify(); }

模板方法模式#

当完成一些过程步骤时是相同的,但具体步骤的细节又是不同时使用。
将相同步骤抽象为模板方法,具体细节由子类具体实现。

Copy
#include<iostream> using namespace std; class People { public: virtual void Ready() = 0; virtual void Start() = 0; void EatTemplate() { Ready(); Start(); } }; class XiaoMing :public People { public: void Ready()override { cout << "端起碗,拿起筷子" << '\n'; } void Start()override { cout << "大口吃" << '\n'; } }; class XiaoBai :public People { public: void Ready()override { cout << "放下碗,拿起勺子" << '\n'; } void Start()override { cout << "挑着吃" << '\n'; } }; int main() { XiaoMing ming; ming.EatTemplate(); XiaoBai bai; bai.EatTemplate(); }

命令模式#

将请求一个操作的对象与执行一个操作的对象分隔开,使得可以对请求进行记录,撤销等操作。
img

Copy
#include<iostream> #include<list> using namespace std; class Receiver { public: void ExcuteCommand1() { cout << "执行命令1" << '\n'; } void ExcuteCommand2() { cout << "执行命令2" << '\n'; } }; class Command { public: Receiver* receiver; Command(Receiver* receiver) { this->receiver = receiver; } virtual void Action() = 0; }; class Command1 :public Command { public: Command1(Receiver* receiver):Command(receiver){} void Action() { receiver->ExcuteCommand1(); } }; class Command2 :public Command { public: Command2(Receiver* receiver) :Command(receiver) {} void Action() { receiver->ExcuteCommand2(); } }; class Invoker { public: list<Command*> command; void AddCommand(Command* c) { command.push_back(c); } void RemoveCommand(Command* c) { command.remove(c); } void Notify() { for (auto i : command) { i->Action(); } } }; int main() { Receiver *receiver = new Receiver(); Command1 *c1 = new Command1(receiver); Command2* c2 = new Command2(receiver); Invoker *i = new Invoker(); i->AddCommand(c2); i->AddCommand(c1); i->Notify(); }

状态模式#

当对象根据不同条件有不同状态时使用。通过不同状态类的局部化,分解过大的条件判断语句。
如下例,需要根据不同时间调整学习的状态,这样需要很多ifelse判断,通过状态模式可以将这些判断分成几个链式连接的对象
img

Copy
#include<iostream> #include<vector> class State; class Study; class InsistState; class GiveUpState; class AfternoonState; class ForenoonState; using namespace std; class State { public: virtual void GetState(Study* s) = 0; }; class Study { public: State* currentState; int currentTime; bool moodGood; Study(int time, bool moodGood) { this->currentTime = time; this->moodGood = moodGood; } void SetState(State* state) { this->currentState = state; } void GetState() { currentState->GetState(this); } }; class GiveUpState :public State { void GetState(Study* s) { cout << "现在是" << s->currentTime << "点,学习?学个屁!" << '\n'; } }; class InsistState :public State { void GetState(Study* s) { cout << "现在是" << s->currentTime << "点,扶我起来,我还能学" << '\n'; } }; class AfternoonState :public State { void GetState(Study* s) { if (s->currentTime < 24) { cout << "现在是" << s->currentTime << "点,有点累,但我还能学" << '\n'; } else { if (s->moodGood == true) { s->SetState(new InsistState()); s->GetState(); } else { s->SetState(new GiveUpState()); s->GetState(); } } } }; class ForenoonState :public State { void GetState(Study* s) { if (s->currentTime <= 12) { cout << "现在是" << s->currentTime << "点,我学的很起劲" << '\n'; } else { s->SetState(new AfternoonState()); s->GetState(); } } }; int main() { int time = 8; bool mood = false; Study* s = new Study(time, mood); s->currentState = new ForenoonState(); s->GetState(); while (time != 24) { time++; s->currentTime = time; s->GetState(); } }

职责链模式#

可以简化对象之间的相互连接,使请求沿着对象连接的链处理下去
下例中,设置leader的后继是boss,当request无法处理,可以传递给boss
img

Copy
#include<iostream> #include<list> using namespace std; class Request { public: string level; string content; Request(string content,string level) { this->content = content; this->level = level; } }; class handler { public: handler* senior; virtual void handle(Request* request) = 0; void setSussessor(handler* senior) { this->senior = senior; } }; class leader :public handler { public: void handle(Request* request) override { if (request->level == "leader") { cout << "leader处理了" << request->content << '\n'; } else { senior->handle(request); } } }; class boss :public handler { public: void handle(Request* request) override { cout << "boss处理了" << request->content << '\n'; } }; int main() { Request request("小明请个假", "boss"); leader *l = new leader(); boss* b = new boss(); l->setSussessor(b); l->handle(&request); }

解释器模式#

对语言解释执行

Copy
#include<iostream> #include<map> using namespace std; class Express { public: void Interpret(string context) { Excute(context[0]); } virtual void Excute(char key) = 0; }; class EndSymbol :public Express { void Excute(char key) { switch(key) { case '!': cout << '\n'; break; case '?': cout << '\.'; break; } } }; class Text :public Express { void Excute(char key) { switch (key) { case '1': cout << "q"; break; case '2': cout << 'w'; break; case '3': cout << 'e'; break; case '4': cout << 'r'; break; case '5': cout << 't'; break; case '6': cout << 'y'; break; case '7': cout << 'u'; break; case '8': cout << 'i'; break; } } }; int main() { string context = "!1785?!"; Express *express; while (context.length() != 0) { if (context[0]=='!' || context[0] == '?') { express = new EndSymbol(); } else { express = new Text(); } express->Interpret(context); context.erase(0, 1); } }

中介模式#

用一个对象封装其它对象间的交互。将各对象网状的通信结构变为中心化的通信,各对象不知其他对象的存在,通过中心化的中介者来协调各对象的通信

Copy
#include<iostream> #include<vector> using namespace std; class Colleage; class Mediator { public: virtual void Send(Colleage* colleage,string message) = 0; }; class Colleage { public: Mediator* mediator; int ID; virtual void Notify(string message) = 0; Colleage(Mediator* mediator,int ID) :mediator(mediator),ID(ID){} }; class Colleage1 :public Colleage { public: Colleage1(Mediator* mediator, int ID):Colleage(mediator,ID){} void Send(string message) { mediator->Send(this,message); } void Notify(string message) { cout << "Colleage1已经收到了信息" << message << '\n'; } }; class Colleage2 :public Colleage { public: Colleage2(Mediator* mediator, int ID) :Colleage(mediator, ID) {} void Send(string message) { mediator->Send(this, message); } void Notify(string message) { cout << "Colleage2已经收到了信息" << message << '\n'; } }; class ConcreteMediator:public Mediator { public: vector<Colleage*> colleages; //广播,除了自己 void Send(Colleage* colleage,string message) override { for (auto i : colleages) { if (i->ID != colleage->ID) { i->Notify(message); } } } }; int main() { ConcreteMediator* m = new ConcreteMediator(); Colleage1 *c1 = new Colleage1(m, 1); Colleage2* c2 = new Colleage2(m, 2); m->colleages.push_back(c1); m->colleages.push_back(c2); c1->Send("今晚统一行动"); }

访问者模式#

使得可以不改变原有对象的情况下定义对其它元素的操作
如下例中不用改变man和woman类,以后对于各种goods商品,定义Cosmetic类,在其内就可以定义好man和woman对不同商品goods的喜欢与否
但是人类这个类必须得相对稳定,不能随便多出man与woman之外多个类。适用于数据结构稳定,算法变化的情况

Copy
#include<iostream> #include<map> using namespace std; class Man; class Woman; class Goods { public: virtual void Manreaction() = 0; virtual void Womanreaction() = 0; }; class Cosmetic :public Goods { public: void Manreaction()override { cout << "Man does not like"<<'\n'; } void Womanreaction()override { cout << "Woman likes"<<'\n'; } }; class Person { public: virtual void Accept(Goods* goods) = 0; }; class Man :public Person { public: void Accept(Goods* goods) override { goods->Manreaction(); } }; class Woman :public Person { public: void Accept(Goods* goods) override { goods->Womanreaction(); } }; int main() { Woman *woman=new Woman(); Man *man=new Man(); Goods *cosmetic=new Cosmetic(); woman->Accept(cosmetic); man->Accept(cosmetic); }

策略模式:#

不同的算法分别实现同一个接口,并封装起来,通过一个对该接口的引用,可以在使用时让不同算法随意替换。
当要实现一堆算法,算法的实现不同,但目标相同,调用方法相同,为了减少算法实现与使用的耦合,考虑使用。
img

Copy
#include<iostream> class Cash { public: virtual double getCash(double money) { return 0; } }; class CashNormal: public Cash { public: double getCash(double money) override { return money; } }; class CashDiscount : public Cash { public: double discount; CashDiscount(double discount) { this->discount = discount; } double getCash(double money) override { return money*discount; } }; class CashReturn : public Cash { public: double condition; double r; CashReturn(double condition,double r) { this->condition = condition; this->r = r; } double getCash(double money) override { if (money >= condition) { return money -r; } else { return money; } } }; class AppointCash { public: Cash* cash; AppointCash(int type) { //简单工厂模式与策略模式的结合 switch (type) { case 0: this->cash = new CashNormal(); break; case 1: this->cash = new CashDiscount(0.5); break; case 2: this->cash = new CashReturn(100,50); break; } } double GetResult(double money) { return cash->getCash(money); } }; int main() { AppointCash *user = new AppointCash(1); std::cout << user->GetResult(100); }

备忘录模式#

用于需要撤销操作,恢复原有类的场景。需要有备忘录类,来保存原有类信息。还需要有管理类,来保存备忘录类
img

Copy
#include<iostream> using namespace std; class Memory { public: Memory(string word) :word(word){} string word; }; class Document { public: Document(string word):word(word){} string word; void getContent() { cout << this->word<<'\n'; } Memory* Store() { return new Memory(word); } void Revoke(Memory* memory) { this->word = memory->word; } }; class Creater { public: Memory *memory; }; int main() { Document d("这是一段话"); d.getContent(); Creater* c = new Creater(); c->memory= d.Store(); d.word = "修改后的一段话"; d.getContent(); d.Revoke(c->memory); d.getContent(); }

迭代器模式#

提供一种方法顺序访问一个聚合对象中各个元素,而不暴露该对象的内部表示
img

Copy
#include<iostream> #include<vector> class ConcreteAgreate; template<typename T> class ConcreteIterator; using namespace std; template<typename T> class Iterator { public: virtual T first() = 0; virtual T next() = 0; virtual bool isEnd() = 0; virtual T currentItem() = 0; }; template<typename T> class ConcreteIterator :public Iterator<T> { private: ConcreteAgreate* aggreate; int current = 0; public: ConcreteIterator(ConcreteAgreate* aggreate) { this->aggreate = aggreate; } T first() override { return aggreate->items[0]; } T next()override { current++; if (current < aggreate->count()) { return aggreate->items[current]; } else { return nullptr; } } bool isEnd()override { if (current >= aggreate->count()) { return true; } else { return false; } } T currentItem()override { return aggreate->items[current]; } }; template<typename T> class Agregate { public: virtual Iterator<T>* createIterator() = 0; virtual int count() = 0; }; //这个类具体实现人的聚合,其中以字符串string表示一个个人,保存在items中 class ConcreteAgreate :public Agregate<string> { public: vector<string> items; ConcreteIterator<string>* createIterator() override { return new ConcreteIterator<string>(this); } void push(string item) { this->items.push_back(item); } int count() override { return this->items.size(); } }; int main() { ConcreteAgreate* a = new ConcreteAgreate(); a->push("李白"); a->push("苏轼"); a->push("李清照"); ConcreteIterator<string>* i = a->createIterator();//创建一个迭代器 string item = i->first(); while (!i->isEnd()) { cout << item << '\n'; item=i->next(); } }
posted @   启林O_o  阅读(87)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
点击右上角即可分享
微信分享提示
CONTENTS