设计模式——行为模式

2024-09-03 06:04
文章标签 设计模式 模式 行为

本文主要是介绍设计模式——行为模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

注意,设计模式的实现并不唯一。

责任链模式

将请求顺序的传递给每一个接收者,直到有一个接收者做出处理。或者一个接收者处理之后继续传递给下一个接收者。

例如 QT 的信号机制。

与装饰器模式的不同:

“责任链的管理者可以相互独立地执行一切操作, 还可以随时停止传递请求。 另一方面, 各种装饰可以在遵循基本接口的情况下扩展对象的行为。 此外, 装饰无法中断请求的传递。”

 

 “中央批下来的公款,本来应该全给到底层,但是中间每层都做一些额外的操作。”

在这个例子中,如果本来中央可以直接给到底层,但是没给,就是要让每层过一遍,这叫装饰模式。但是如果中央没办法直接给到底层,不得已必须层层传递,这叫责任链模式。

class Request;class Layer {virtual bool handle(Request request) = 0;
};class LayerImpl : public Layer {bool handle(Request request) override {if ( /* 我能处理 */ ) {// 处理return true;}for (auto layer : next_layers) {if (layer.handle(request)) {return true;}}}
private:std::vector<Layer > next_layers;
};

 命令模式

当一项业务操作代码会被复制成多份时,将其设计为一个命令。

例如,通常编辑器上有“复制”按钮,也可以通过 Ctrl+C 复制,这两项都是对剪切板的操作,可以把它们叫做 copy 命令,发送至剪切板对象。

class String;class Command {virtual void execute() = 0;
};class CopyCommand : public Command {void execute() override;
};class CutCommand : public Command {void execute() override;
};class Button {void set_on_click(Command command);void on_click() {command.execute();}private:Command command;
};class Shortcut {void set_shortcut(String key, Command command);
};int main()
{CopyCommand copy_command;CutCommand cut_command;Shortcut shortcuts;Button copy_button;copy_button.set_on_click(copy_command);shortcuts.set_shortcut("Ctrl+C", copy_command);Button cut_button;cut_button.set_on_click(cut_command);shortcuts.set_shortcuts("Ctrl+X", cut_command);
}

个人理解:

把操作变成对象,用于存储、传递。

 迭代器模式

当你希望你操作的对象在不暴露数据成员的情况下提供遍历方法时,你可以要求该对象提供迭代器。

你希望在不暴露数据成员的情况下提供访问数据成员的方法时,你可以提供迭代器。

例如 std::vector,std::queue。

class Spammer;
class Stringclass Server {class SpammerIterator {virtual bool next() = 0;virtual String get_email() = 0;};void email_to(SpammerIterator spammer);
};class WeChatContact {class WechatSpammerIterator : public SpammarIterator {bool next() override;String get_email() override;}SpammerIterator* create_iterator();private:std::vector<Spammer> spammers;
};class QQContact {class QQSpammerIterator : public SpammarIterator {bool next() override;String get_email() override;}SpammerIterator* create_iterator();private:std::vector<Spammer> spammers;
};int main()
{WeChatContact wechat_contact;QQContact qq_contact;Server server;SpammerIterator* spammer_iterator;if (/*using WeChat*/) {spammer_iterator = wechat_contact.create_iterator();}else if (/*using QQ*/) {spammer_iterator = qq_contact.create_iterator();}while (spammer_iterator.next()) {server.email_to(spammer_iterator->get_email();}
}

你也可以提供一个 for_each 方法。

中介者模式

多个对象之间的关系错综复杂,把这些关系抽取为单独的一个类,这个类是中介者。

与其他模式的区别

  • 责任链模式:一个请求——多个接收者
  • 命令模式:多个对象发出同一个请求
  • 中介者模式:抽象出请求者与接收者之间的联系
  • 观察者:接受者选择请求者

 例如在 A,B,C 三个对象中,每个对象负责一项业务。你希望 A 业务完成后,要修改 B 对象的状态。B 业务完成后,修改 C 对象的状态;C 业务完成后,修改 A 对象的状态。抽取出一个类,持有对三个对象的引用,当 A,B,C 任一业务完成后通知此对象,此对象根据事件通知执行后续。

enum class Events;class Mediator {void notify(Events event) {if (/* event 为 A */) {b.set_data();}else if (/* event 为 B */) {c.set_data();}else if (/* event 为 C */) {a.set_data();}}private:A& a;B& b;C& c;
};class A {void server() {// 业务 Amediator.notify(Events::A);}void set_data();private:Mediator& mediator;
};class B {void server() {// 业务 Bmediator.notify(Events::B);}void set_data();private:Mediator& mediator;
};class C {void server() {// 业务 Cmediator.notify(Events::C);}void set_data();private:Mediator& mediator;
};

备忘录模式

当你需要为对象创建快照和从快照中还原对象时,这项工作可以委托给一个快照对象,从而避免暴露对象的数据成员。

class Data; // 二进制数据class Object {
public:// 作为嵌套类可以访问 Object 的成员class SnapShot {Data create();void restore(Data data);    private:Object& object;};
private:int a;double b;std::string c;
};

观察者模式

又称订阅者模式。

把请求者发送请求到接收者 改为 接受者订阅请求者的请求。

例如 Kafka,逛不同网站时订阅该网站的商品邮件。

class Request;
class Endpoint; // 这个名称通常表示 IP:PORT,例如 "127.0.0.1:8080"class Server {void on_request(Request request) {for (auto subscriber : subscribers) {send(subscriber, request);}}void register(Endpoint endpoint) {subscribers.push_back(endpoint);}private:std::vector<Endpoint> subscribers;
};class Client {Endpoint get_endpoint();void receive();void on_request(Request request) {// 处理请求}
};

状态模式

相同的接口在不同状态下表现出不同的行为。

例如视频暂停时、播放时,双击屏幕的行为不同。

class State {virtual void on_double_click() = 0;
};class PauseState {void on_double_click() override {// 隐藏暂停图标,继续播放}
};class PlayingState {void on_double_click() override {// 显示暂停图标,暂停播放}
};class VideoPlayer {void change_state(State state);void on_double_click() {state.on_double_click();}
};

策略模式

一个需要替换不同算法的场景中,我们可以将算法抽象出来。

例如地图app中,从一个位置到另一个位置,因为交通方式不同,有不同的路线和算法。

class Strategy {virtual int execute(int a, int b) = 0;
};class AddStrategy {int execute(int a, int b) override {return a + b;}
};class SubStrategy {int execute(int a, int b) override {return a - b;}
};class MulStrategy {int execute(int a, int b) override {return a * b;}
};int main()
{int a,b;Strategy strategy;if (/*add*/) {strategy = AddStrategy();}else if (/*sub*/) {strategy = SubStrategy();}else if (/*mul*/) {strategy = MulStrategy();}strategy.execute();
}

在某些语言中,你可以使用函数对象代替多态。

与其它模式的关系:

  • 状态模式包含了具体了业务。策略模式期望算法无需关心业务。
  • 命令模式包装操作。策略模式抽象算法。
  • 装饰模式更改外表。策略模式替换内核。

 模板方法模式

将一系列步骤抽象,让客户端可以替换每一个步骤的工作。

  • 抽象步骤必须由各个子类来实现
  • 可选步骤已有一些默认实现, 但仍可在需要时进行重写

“还有另一种名为钩子的步骤。 钩子是内容为空的可选步骤。 即使不重写钩子, 模板方法也能工作。 钩子通常放置在算法重要步骤的前后, 为子类提供额外的算法扩展点。”

// 使用函数对象代替多态
class Function;class Work {void set_step1(Function step1);void set_hook(Function hook);void set_step2(Function step2);void set_step3(Function step3);void set_step4(Function step4);void work() {step1();hook();step2();step3();step4();}private:Function step1;Function hook;Function step2;Function step3;Function step4;
};

class BaseWork {virtual void step1() = 0;virtual void hook(); // 默认实现virtual void step2() = 0;virtual void step3() = 0;virtual void step4() = 0;void work() {step1();hook();step2();step3();step4();}
};class Work : public BaseWork {void step1() override;void step2() override;void step3() override;void step4() override;
};

访问者模式

访问者模式是一种行为设计模式, 它能将算法与其所作用的对象隔离开来。

 对于继承自 X 的 A,B,C 三个派生类,它们重载的同一个算法函数实现不同,如何实现?简单,override 即可。如果甲方要求修改算法,但又不希望调整已经稳定的 A,B,C 的代码,该如何呢?

简单的重载无法满足该需求。访问者模式将算法实现在作用对象外部,从而不影响作用对象的代码。

class Parameters;class Visitor {void for_A(Parameters param) {// 对 A 的算法}void for_B(Parameters param) {// 对 B 的算法}void for_C(Parameters param) {// 对 C 的算法}
};class Base {virtual accept(Visitor visitor) = 0;
};class A : public Base {void accept(Visitor visitor) {visitor.for_A(Parameters());}
};class B : public Base {void accept(Visitor visitor) {visitor.for_B(Parameters());}
};class C : public Base {void accept(Visitor visitor) {visitor.for_C(Parameters());}
};

这篇关于设计模式——行为模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1132227

相关文章

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

模版方法模式template method

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/template-method 超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 上层接口有默认实现的方法和子类需要自己实现的方法

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

迭代器模式iterator

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/iterator 不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素

《x86汇编语言:从实模式到保护模式》视频来了

《x86汇编语言:从实模式到保护模式》视频来了 很多朋友留言,说我的专栏《x86汇编语言:从实模式到保护模式》写得很详细,还有的朋友希望我能写得更细,最好是覆盖全书的所有章节。 毕竟我不是作者,只有作者的解读才是最权威的。 当初我学习这本书的时候,只能靠自己摸索,网上搜不到什么好资源。 如果你正在学这本书或者汇编语言,那你有福气了。 本书作者李忠老师,以此书为蓝本,录制了全套视频。 试

利用命令模式构建高效的手游后端架构

在现代手游开发中,后端架构的设计对于支持高并发、快速迭代和复杂游戏逻辑至关重要。命令模式作为一种行为设计模式,可以有效地解耦请求的发起者与接收者,提升系统的可维护性和扩展性。本文将深入探讨如何利用命令模式构建一个强大且灵活的手游后端架构。 1. 命令模式的概念与优势 命令模式通过将请求封装为对象,使得请求的发起者和接收者之间的耦合度降低。这种模式的主要优势包括: 解耦请求发起者与处理者

springboot实战学习(1)(开发模式与环境)

目录 一、实战学习的引言 (1)前后端的大致学习模块 (2)后端 (3)前端 二、开发模式 一、实战学习的引言 (1)前后端的大致学习模块 (2)后端 Validation:做参数校验Mybatis:做数据库的操作Redis:做缓存Junit:单元测试项目部署:springboot项目部署相关的知识 (3)前端 Vite:Vue项目的脚手架Router:路由Pina:状态管理Eleme

状态模式state

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/state 在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。 在状态模式中,player.getState()获取的是player的当前状态,通常是一个实现了状态接口的对象。 onPlay()是状态模式中定义的一个方法,不同状态下(例如“正在播放”、“暂停

软件架构模式:5 分钟阅读

原文: https://orkhanscience.medium.com/software-architecture-patterns-5-mins-read-e9e3c8eb47d2 软件架构模式:5 分钟阅读 当有人潜入软件工程世界时,有一天他需要学习软件架构模式的基础知识。当我刚接触编码时,我不知道从哪里获得简要介绍现有架构模式的资源,这样它就不会太详细和混乱,而是非常抽象和易

使用Spring Boot集成Spring Data JPA和单例模式构建库存管理系统

引言 在企业级应用开发中,数据库操作是非常重要的一环。Spring Data JPA提供了一种简化的方式来进行数据库交互,它使得开发者无需编写复杂的JPA代码就可以完成常见的CRUD操作。此外,设计模式如单例模式可以帮助我们更好地管理和控制对象的创建过程,从而提高系统的性能和可维护性。本文将展示如何结合Spring Boot、Spring Data JPA以及单例模式来构建一个基本的库存管理系统