设计模式实战精讲:行为型模式
本篇博客包含11种设计模式,自从学习这么多种设计模式后,我的心态也发生了变化,或许不会存在永远按照设计模式来设计的程序,一个项目也可能存在符合多种设计模式的情况,但是无论正确与否,我觉得可读性强的,利于维护的,方便增加功能的项目就是好项目。(例如有三个对象,调用顺序是A->B->C,把所有的项目都先传递给A,A拿到所有的项目后,把属于自己负责的项目留下来,把剩下的传递给B,然后B把属于自己的留下来,把不属于自己的再传递给C)1.定义抽象元素类:定义访问者可调用的函数,访问者通过该函数实现修改元素内的内容。

1.前言
前言
本篇《C++设计模式(下):行为型模式》作为设计模式的最后一篇博客,也会以一如既往的格式对其中所含的设计模式进行讲解。本篇博客包含11种设计模式,自从学习这么多种设计模式后,我的心态也发生了变化,或许不会存在永远按照设计模式来设计的程序,一个项目也可能存在符合多种设计模式的情况,但是无论正确与否,我觉得可读性强的,利于维护的,方便增加功能的项目就是好项目。所以学完设计模式,许多设计的思想我们都可以Copy到自己的项目中

图1.行为型模式区分示意
模板模式
1.模板模式:在基类中定义了一个函数的框架, 允许子类在不修改结构的情况下重写函数的实现。在抽象类中统一操作步骤,并规定好接口,让子类实现接口。这样可以把各个具体的子类和操作步骤解耦合。当多个类的算法除一些细微不同之外几乎完全一样时, 则可以使用模板模式(其实就是继承抽象类,子类实现函数)
2.模板模式实现步骤:
1.定义抽象类:定义了模板方法,模板方法是部分实现的,将一个算法作为一个系列步骤进行封装,其中一些步骤延迟到子类中实现
2.定义具体类:继承自抽象类,实现模板方法中的未实现的步骤
3.优点:允许客户端重写一个类中的特定部分,使得模板方法其他部分修改对其所造成的影响减小,可将重复代码提取到一个抽象类中,提高封装
4.缺点:部分客户端会受到模板方法框架的限制,维护工作会困难
5.模板模式实现代码:
class AbstractClass{ //抽象类protected: vector<double> components;public: //构造函数 AbstractClass(const std::vector<double>& comps) : components(comps) {} void templateMethod() { //模板方法 //定义算法的骨架 step1(); step2(); step3(); } //基本函数,可以在抽象类中实现 void step1(){ cout << "Hello World" << endl; } //纯虚函数,子类重写 virtual void step2()=0; //基本函数,可以在抽象类中实现 void step3(){ cout << "Wild_Pointer" << endl; }};class ConcreteClass : public AbstractClass{ //具体类public: //构造函数 ConcreteClass(const vector<double>& comps) : AbstractClass(comps) {} //重写纯虚函数 void step2() override { cout << "子类重写纯虚函数" << endl; }};int main() { ConcreteClass concreteClass({1.1, 2.2, 3.3}); concreteClass.templateMethod(); //执行整个模板算法 return 0;}命令模式
1.命令模式:将请求封装为一个对象,从而允许用户使用不同的请求、队列或日志请求来参数化其他对象。命令模式也支持可撤销的操作。通常用于将操作请求者和执行者解耦,让调用操作的对象不需要知道具体是如何执行的(当对象A调用对象B的多个函数时,可以使用命令模式,将这些函数封装成一个对象,调用函数改换成调用对象)
2.命令模式实现步骤:
1.定义抽象命令类:声明执行操作的方法
2.定义具体命令类:将调用的对象作为属性,实现执行操作的方法,方法中调用对象的函数
3.定义调用对象和被调用对象,将被调用对象作为具体命令类的属性,具体命令类作为调用对象的属性,通过调用对象中的函数对具体命令类调用,从而实现间接调用
3.优点:符合单一职责原则和开闭原则,实现操作的延迟执行
4.缺点:代码可能会变得更加复杂,因为是间接调用
5.命令模式实现代码:
class Receiver { //被调用的类public: void action() { std::cout << "Executing action in Receiver" << std::endl; }};class Command { //抽象命令类public: virtual ~Command() {} virtual void execute() = 0; //命令函数};class ConcreteCommand : public Command { //具体命令类private: shared_ptr<Receiver> receiver; //被调用的对象public: //构造函数 ConcreteCommand(shared_ptr<Receiver> r) : receiver(r) {} void execute() override { receiver->action(); }};class Invoker { //调用者private: Command* command; //定义具体命令类对象public: //初始化具体命令类对象 void setCommand(Command* cmd) { command = cmd; } //调用命令 void invoke() { if(command) { command->execute(); } }};int main() { auto receiver = make_shared<Receiver>(); Command* command = new ConcreteCommand(receiver); Invoker invoker; invoker.setCommand(command); invoker.invoke(); //执行命令 delete command; return 0;}责任链模式
1.责任链模式:允许你将一个请求沿着处理者链进行传递,直到有一个处理者处理它为止。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者(例如有三个对象,调用顺序是A->B->C,把所有的项目都先传递给A,A拿到所有的项目后,把属于自己负责的项目留下来,把剩下的传递给B,然后B把属于自己的留下来,把不属于自己的再传递给C)
2.责任链模式实现步骤:
1.定义抽象处理者类:定义一个接口,定义一个方法用于处理请求
2.定义具体处理者类:包含对下一个处理者的引用。一个具体处理者知道如何履行处理职责,或者将请求传递给链中的下一个处理者
3.优点:符合单一职责原则和开闭原则,可以控制请求处理的顺序
4.缺点:部分请求可能未被处理
5.责任链模式实现代码:
class Handler{ //定义抽象处理者类public: virtual ~Handler() {} virtual void handleRequest() = 0; //处理函数 shared_ptr<Handler> successor;};class ConcreteHandlerA : public Handler{ //定义具体处理者类public: void handleRequest() override { //处理函数 if (this->successor) { cout << "不可以处理,传递给下一个处理者" << endl; this->successor->handleRequest(); } else { cout << "处理者A可以处理" << endl; } }};class ConcreteHandlerB : public Handler{ //定义具体处理者类public: void handleRequest() override { if (this->successor) { cout << "不可以处理,传递给下一个处理者" << endl; this->successor->handleRequest(); } else { cout << "处理者B可以处理" << endl; } }};int main() { //定义处理者 auto handlerA = make_shared<ConcreteHandlerA>(); auto handlerB = make_shared<ConcreteHandlerB>(); //定义处理者链 handlerA->successor = handlerB; handlerB->successor = nullptr; //链的末端 handlerA->handleRequest(); // 发送请求 return 0;}策略模式
1.策略模式:定义一系列函数, 并将每种函数分别放入独立的类中, 以使函数的对象能够相互替换,能够将对象关联至可以不同方式执行特定子任务的不同子对象, 从而以间接方式在运行时更改对象行为
2.策略模式实现步骤:
1.定义抽象策略类:定义所有支持的算法的公共接口
2.定义具体策略类:实现 接口的具体算法
3.定义环境类:持有一个接口的引用,用以使用策略
3.优点:符合开闭原则,在运行时可以切换对象内调用的函数,将函数的实现和使用函数的代码隔离开来
4.缺点:会让程序过于复杂
5.策略模式实现代码:
class Strategy{ //定义抽象策略类public: virtual ~Strategy() {} virtual void execute() = 0; //接口函数};class ConcreteStrategyA : public Strategy{ //定义具体策略类public: void execute() override { //实现接口函数 cout << "实现接口A" << endl; }};class ConcreteStrategyB : public Strategy{ //定义具体策略类public: void execute() override { cout << "实现接口B" << endl; }};class Context{ //定义环境类private: unique_ptr<Strategy> strategy; //定义抽象策略类的指针public: //给赋值抽象策略类指针 void setStrategy(unique_ptr<Strategy> s) { strategy = move(s); //需要实现什么具体策略,就传入什么参数 } void executeStrategy() { if(strategy) { strategy->execute(); } }};int main() { Context context; context.setStrategy(std::make_unique<ConcreteStrategyA>()); context.executeStrategy(); //执行具体策略A context.setStrategy(std::make_unique<ConcreteStrategyB>()); context.executeStrategy(); //执行具体策略B return 0;}观察者模式
1.观察者模式:当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态当应用中的一些对象必须观察其他对象时,可使用该模式
2.观察者模式实现步骤:
1.定义抽象被观察类:被观察的对象,抽象基本的属性状态及其他操作
2.定义具体被观察类:被观察的对象以及具体实现,何时触发刷新等
3.定义抽象观察者类:定义抽象观察者的具体逻辑处理,刷新触发什么函数等
4.定义具体观察者类:观察者的具体实现,得到通知后将完成一些具体的业务逻辑处理
3.优点:符合开闭原则,可以在运行时建立对象之间的联系,能让耦合的双方都依赖于抽象,而不是依赖于具体
4.缺点:通知观察者可能会花费很多时间
5.观察者模式实现代码:
class Observer { //定义抽象观察者类public: virtual ~Observer(){} virtual void update() = 0;};class Subject { //定义抽象被观察类private: list<Observer*> observers;public: void attach(Observer* o){ //加入观察者 observers.push_back(o); } void detach(Observer* o){ //删除观察则 observers.remove(o); } void notify(){ //状态刷新函数 for(Observer* o : observers) { o->update(); } }};class ConcreteObserver : public Observer { //定义具体观察者类private: int state;public: void update() override { //状态发生变化 cout << "状态更新: " << state << sendl; }};class ConcreteSubject : public Subject { //定义具体被观察类private: int state; //状态public: void changeState(int newState) { //状态更新函数 state = new State; notify(); //状态更新,触发操作 }};int main() { ConcreteSubject subject; ConcreteObserver observer; subject.attach(&observer); subject.changeState(1); //通知观察者 subject.detach(&observer); subject.changeState(2); //观察者不会收到通知 return 0;}访问者模式
1.访问者模式:分离对象的数据和行为,使用访问者模式模式,可以不修改已有类的情况下,增加新的操作角色和职责(当需要修改元素的时候,不会直接调用元素类的函数进行修改,而是定义访问者类,通过访问者类的具体函数来修改元素类的内容。当内容需要改变时,只需要修改访问者类)
2.访问者模式实现步骤:
1.定义抽象元素类:定义访问者可调用的函数,访问者通过该函数实现修改元素内的内容
2.定义具体元素类:实现访问者可调用的函数
3.定义抽象访问者类:定义需要修改元素类内容的函数
4.定义具体访问者类:实现需要修改元素类内容的函数
5.定义对象结构类,该类用于调用调用元素对象,通过元素对象的可被访问者修改的函数,调用访问者的具体实现函数,达成修改内容的目的
3.优点:符合开闭原则和单一职责原则,访问者对象可以在与各种对象交互时收集一些有用的信息
4.缺点:每次在对象结构中添加或移除一个元素类时, 要更新具体的访问者。在访问者同某个元素类进行交互时,可能没有访问元素私有成员变量和方法的必要权限
5.访问者模式实现代码:
class Element{ //定义抽象元素类public: virtual ~Element() {} virtual void accept(Visitor* visitor) = 0;};class ConcreteElementA : public Element{ //定义具体元素类Apublic: void accept(Visitor* visitor) override { visitor->visit(this); }};class ConcreteElementB : public Element { //定义具体元素类Bpublic: void accept(Visitor* visitor) override { visitor->visit(this); }};class Visitor { //定义抽象访问者类public: virtual ~Visitor() {} virtual void visit(ConcreteElementA* element) = 0; virtual void visit(ConcreteElementB* element) = 0;};class ConcreteVisitor : public Visitor{ //定义具体访问者类public: void visit(ConcreteElementA* element) override { cout << "Visiting ConcreteElementA"; //定义访问ConcreteElementA的操作 } void visit(ConcreteElementB* element) override { cout << "Visiting ConcreteElementB"; //定义访问ConcreteElementB的操作 }};class ObjectStructure{ //定义对象结构类private: vector<Element*> elements;public: //添加元素 void addElement(Element* element) { elements.push_back(element); } //使用元素 void operate(Visitor* visitor) { for (Element* element : elements) { element->accept(visitor); } }};int main() { ObjectStructure structure; //定义对象结构类 //添加元素 structure.addElement(new ConcreteElementA()); structure.addElement(new ConcreteElementB()); Visitor* visitor = new ConcreteVisitor(); //定义访问者类 structure.operate(visitor); //通过对象结构调用元素对象,通过元素对象再调用访问者的具体实现函数 delete visitor; return 0;}中介者模式
1.中介者模式:能减少对象之间混乱无序的依赖关系,该模式会限制对象之间的直接交互, 迫使它们通过一个中介者对象进行合作,将对象间的所有关系抽象成为一个单独的类, 以使对于特定组件的修改工作独立于其他组件
2.中介者模式实现步骤:
1.定义一个中介者类:定义对象到中介者对象的接口
2.定义一个具体中介者类:实现抽象接口,并且实现关联类数据处理
3.定义抽象同事类 :多个关联类之间的交互操作的抽象
4.定义一个或多个具体同事类:实现抽象,通过中介者类完成操作
3.优点:符合单一职责原则和开闭原则,减轻应用中多个组件间的耦合情况你可以更方便地复用各个组件
4.缺点:中介者可能会演化成为上帝对象(上帝对象就是指类承载太多的功能,导致它变得过于复杂和难以维护)
5.中介者模式实现代码:
class Mediator { //定义抽象中介者类public: virtual ~Mediator() {} virtual void send(const string& message, Colleague* colleague) = 0;};class ConcreteMediator : public Mediator{ //定义具体中介类private: std::vector<Colleague*> colleagues;public: void registerColleague(Colleague* colleague) { colleagues.push_back(colleague); } void send(const string& message, Colleague* colleague) override { for (auto* c : colleagues) { if (c != colleague) { c->receive(message); } } }};class Colleague{ //定义抽象同事类protected: Mediator* mediator;public: Colleague(Mediator* m) : mediator(m) {} virtual void send(const string& message) = 0; virtual void receive(const string& message) = 0;};class ConcreteColleagueA : public Colleague{ //定义具体同事类public: ConcreteColleagueA(Mediator* m) : Colleague(m) {} void send(const string& message) override { mediator->send(message, this); } void receive(const string& message) override { cout << "Colleague A received: " << message; }};class ConcreteColleagueB : public Colleague{ //定义具体同事类public: ConcreteColleagueB(Mediator* m) : Colleague(m) {} void send(const std::string& message) override { mediator->send(message, this); } void receive(const std::string& message) override { std::cout << "Colleague B received: " << message << std::endl; }};int main() { ConcreteMediator mediator; //定义具体中介类对象 //定义具体同事类对象 ConcreteColleagueA colleagueA(&mediator); ConcreteColleagueB colleagueB(&mediator); //添加同事类对象到中介类对象中 mediator.registerColleague(&colleagueA); mediator.registerColleague(&colleagueB); //通过中介类访问同事类 colleagueA.send("Hello from A"); colleagueB.send("Hello from B"); return 0;}备忘录模式
1.备忘录模式:允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态,复制对象中的全部状态 (包括私有成员变量), 并将其独立于对象进行保存。备忘录模式让对象自行负责创建其状态的快照。 任何其他对象都不能读取快照, 有效地保障了数据的安全性
2.备忘录模式实现步骤:
1.定义发起者类:用于负责创建一个备忘录,用以记录当前时刻的内部状态。当需要恢复状态时,它使用备忘录中保存的状态信息
2.定义备忘录类:负责存储发起者类对象的内部状态,并保护其不被外部直接访问。备忘录对象通常只对创建它的对象可见
3.定义管理者类:负责保存备忘录对象,并在需要时将其提供给发起者类以恢复状态。管理者不知晓备忘录中存储的具体状态细节
3.优点:在不破坏对象封装情况的前提下创建对象状态快照,通过让负责人维护发起者状态历史记录来简化发起者类代码
4.缺点:中介者可能会演化成为上帝对象(上帝对象就是指类承载太多的功能,导致它变得过于复杂和难以维护)
5.备忘录模式实现代码:
class Memento { //定义备忘录类private: string state;public: Memento(const std::string& savedState) : state(savedState) {} // 获取备忘录中的状态 std::string getState() const { return state; }};class Originator { //定义发起者类private: string state;public: //获取当前状态 string getState() const{ return state; } //设置状态 void setState(const std::string& newState) { state = newState; } //创建备忘录 shared_ptr<Memento> saveStateToMemento() { return std::make_shared<Memento>(state); } //从备忘录对象中恢复状态 void getStateFromMemento(const shared_ptr<Memento>& memento) { state = memento->getState(); }};class Caretaker { //定义管理者类private: //备忘录列表 list<shared_ptr<Memento>> mementoList;public: //添加备忘录 void add(const shared_ptr<Memento>& memento) { mementoList.push_back(memento); } //获取备忘录 shared_ptr<Memento> get(int index) { return mementoList.at(index); }};int main() { Originator originator; //定义发起者对象 Caretaker caretaker; //定义管理者对象 //设置发起人的初始状态 originator.setState("State #1"); cout << "发起人对象的初始状态: " << originator.getState(); //使用管理者对象保存发起人当前状态 caretaker.add(originator.saveStateToMemento()); //修改状态 originator.setState("State #2"); cout << "发起人对象的当前状态: " << originator.getState(); //通过管理者对象恢复到保存的状态 originator.getStateFromMemento(caretaker.get(0)); cout << "回复到初始状态: " << originator.getState(); return 0;}状态模式
1.状态模式:在一个对象的内部状态变化时改变其行为, 将所有特定于状态的代码抽取到一组独立的类中,使其看上去就像改变了自身所属的类一样。可以在独立于其他状态的情况下添加新状态或修改已有状态, 从而减少维护成本
2.状态模式实现步骤:
1.定义上下文类:维护一个具体状态类的对象,这个对象定义当前的状态
2.定义抽象状态类:定义一个接口用于封装与上下文类的一个特定状态相关的行为
3.定义具体状态类:实现抽象状态类的接口,负责处理与状态相关的行为
3.优点:符合单一职责原则和开闭原则,通过消除臃肿的状态机条件语句简化上下文代码
4.缺点:如果具体状态类只有很少的几个状态, 或者很少发生改变, 那么应用该模式可能会显得小题大作
5.状态模式实现代码:
class State{ //定义抽象状态类public: virtual ~State() {} virtual void on() = 0; virtual void off() = 0;};class OnState : public State{ //定义具体状态类:开状态public: void on() override{ cout << "The switch is already on."; } void off() override{ cout << "Turning off the switch."; }};class OffState : public State{ //定义具体状态类:关状态public: void on() override{ cout << "Turning on the switch."; } void off() override { cout << "The switch is already off."; }};class Switch{ //定义上下文类private: State* state; //状态类对象public: Switch() : state(nullptr) {} ~Switch() { delete state; } //设置状态 void setState(State* newState) { delete state; state = newState; } //打开状态 void on(){ state->on(); } //关闭状态 void off(){ state->off(); }};int main() { Switch switchMachine; //定义上下文对象 switchMachine.setState(new OnState()); //设置开状态 switchMachine.on(); switchMachine.setState(new OffState()); //设置关状态 switchMachine.off(); switchMachine.setState(new OnState()); //设置新的状态 switchMachine.off(); return 0;}解释器模式
1.解释器模式:用于定义一个语言的语法规则,并构建一个解释器类来解释该语言中的句子,这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式常被用在 SQL 解析、符号处理引擎等
2.解释器模式实现步骤:
1.定义解释器上下文环境类:用来存储解释器的上下文环境,比如需要解释的文法,一般用来传递被所有解释器共享的数据
2.定义解释器抽象类:定义解释器的接口,约定解释器的解释操作
3.定义终结符解释器的具体实现类:用来实现语法规则中和终结符相关的操作
4.定义非终结符解释器:用来实现语法规则中非终结符相关的操作,通常一个解释器对应一个语法规则,可以包含其他解释器为
3.优点:扩展性好,容易实现
4.缺点:执行效率较低,会引起类膨胀。解释器模式中的每条规则至少需要定义一个类,文法规则很多时,类的个数将急剧增加,导致系统难以管理与维护
5.解释器模式实现代码:
class Expression { //定义抽象表达式类public: virtual int Interpreter(map<string, int>& var) = 0;};class VarExpression :public Expression { //定义变量解析器类public: VarExpression(string key){ this->key = key; } int Interpreter(map<string, int>& var){ return var[key]; }private: string key; };class SymbolExpression :public Expression{ //定义运算符解析器类protected: Expression* left; Expression* right;public: SymbolExpression(Expression* left, Expression* right) :left(left), right(right){} Expression* GetLeft() { return left; } Expression* GetRight() { return right; } };class AddExpresion :public SymbolExpression { //定义加法解析器类public: AddExpresion(Expression* left, Expression* right) : SymbolExpression(left, right) {} int Interpreter(map<string, int>& var){ return left->Interpreter(var) + right->Interpreter(var); }};class SubExpresion :public SymbolExpression { //定义减法解析器类public: SubExpresion(Expression* left, Expression* right) : SymbolExpression(left, right) {} int Interpreter(map<string, int>& var){ return left->Interpreter(var) - right->Interpreter(var); }};class Calculator { //定义解析器封装类 封装调用接口private: Expression* expression;public: //解析表达式,构建语法树 a+b-c Calculator(string expStr) { expression = NULL; stack<Expression*> stkExp; Expression* left = NULL; Expression* right = NULL; for(int i=0;i<expStr.length();i++){ switch (expStr[i]){ case '+': left = stkExp.top(); stkExp.pop(); right = new VarExpression(expStr.substr(++i, 1)); stkExp.push(new AddExpresion(left, right)); break; case '-': left = stkExp.top(); stkExp.pop(); //从表达式中取出+号后面的右操作数,并生成终结符解析对象 right = new VarExpression(expStr.substr(++i, 1)); //将左右操作数相加,并把结果放入栈中 stkExp.push(new SubExpresion(left, right)); break; default: stkExp.push(new VarExpression(expStr.substr(i, 1))); } } if (!stkExp.empty()){ expression = stkExp.top(); stkExp.pop(); } } int Run(map<string, int>& var){ return (expression == NULL) ? 0 : expression->Interpreter(var); }};int main(){ string expstr = "a+b-c"; //定义解释的语句 map<string, int> var; var["a"] = 300; var["b"] = 20; var["c"] = 30; Calculator cal(expstr); //定义解析器 cout << cal.Run(var) << endl; //对语句进行解释 return 0;}迭代器模式
1.迭代器模式:能在不暴露集合底层表现形式(类似于C++STL中的迭代器iterator)的情况下遍历集合中所有的元素能避免客户端在直接与集合交互时执行错误或有害的操作
2.迭代器模式实现步骤:
1.定义抽象迭代器类:定义了迭代器的接口,通常包含移动到下一个元素,检查是否有下一个元素,可选,移除当前元素等方法。
2.定义具体迭代器类:实现了抽象迭代器接口,跟踪当前遍历的位置,并能具体实现迭代器方法
3.定义抽象聚合类:包含多个元素的容器,提供了创建迭代器对象的方法
4.定义具体聚合类:实现了抽象聚合类的接口,返回一个与该具体聚合类型兼容的具体迭代器对象
3.优点:符合单一职责原则和开闭原则,无需修改现有代码你可以并行遍历同一集合,因为每个迭代器对象都包含其自身的遍历状态
4.缺点:对于某些特殊集合, 使用迭代器可能比直接遍历的效率低
5.迭代器模式实现代码:
class Container{ //定义一个容器类,用于存储一系列元素private: vector<int> data;public: //添加元素到容器 void add(int elem){ data.push_back(elem); } //创建迭代器 auto createIterator(){ return svector<int>::iterator(data.begin()); }};class Iterator{ //定义迭代器类private: Container& container; vector<int>::iterator current;public: Iterator(Container& c) : container(c), current(c.createIterator()) {} //移动到下一个元素 void next(){ ++current; } //获取当前元素 int getCurrent(){ return *current; } //检查是否还有下一个元素 bool hasNext(){ return current != container.data.end(); }};int main() { // 创建容器对象并添加元素 Container myContainer; myContainer.add(10); myContainer.add(20); myContainer.add(30); //创建迭代器对象并使用它遍历容器 Iterator it(myContainer); while (it.hasNext()) { cout << it.getCurrent() << " "; it.next(); } return 0;}行为型模式总结
- 模板方法模式:通过定义一套流程模板进行流程化处理
- 命令模式:请求成为命令,允许多种对象调用修改参数
- 责任链模式:对象连接成为链,通过链进行传递请求
- 策略模式:封装不同算法,算法之间可以互相转换
- 中介者模式:类与类之间间接交互,中介者类做转发操作
- 观察者模式:状态发生改变通知观察者
- 备忘录模式:保存对象状态,可以进行回滚
- 访问者模式:通过对象结构调用元素对象,通过元素对象再调用访问者的具体实现函数
- 状态模式:根据不同的状态做不同的行为
- 解释器模式:给定规则,定义语法,定义解释器,做句子分析
- 迭代器模式:提供一个对象的访问复合对象的各个元素