设计模式之责任链

news/2024/9/22 12:53:18 标签: 设计模式, c++

一、责任链设计模式概念

责任链模式(Chain Of Responsibility) 是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。 将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

 适用场景

  • 当程序需要使用不同方式处理不同种类请求, 而且请求类型和顺序预先未知时, 可以使用责任链模式。
  • 当必须按顺序执行多个处理者时, 可以使用该模式。
  • 如果所需处理者及其顺序必须在运行时进行改变, 可以使用责任链模式

责任链设计模式的结构

  1. 处理者 (Handler) 声明了所有具体处理者的通用接口。 该接口通常仅包含单个方法用于请求处理, 但有时其还会包含一个设置链上下个处理者的方法。

  2. 基础处理者 (Base Handler) 是一个可选的类, 你可以将所有处理者共用的样本代码放置在其中。

    通常情况下, 该类中定义了一个保存对于下个处理者引用的成员变量。 客户端可通过将处理者传递给上个处理者的构造函数或设定方法来创建链。 该类还可以实现默认的处理行为: 确定下个处理者存在后再将请求传递给它。

  3. 具体处理者 (Concrete Handlers) 包含处理请求的实际代码。 每个处理者接收到请求后, 都必须决定是否进行处理, 以及是否沿着链传递请求。

    处理者通常是独立且不可变的, 需要通过构造函数一次性地获得所有必要地数据。

  4. 客户端 (Client) 可根据程序逻辑一次性或者动态地生成链。 值得注意的是, 请求可发送给链上的任意一个处理者, 而非必须是第一个处理者。

代码如下:

            问题:开发一款故障报修系统,不同的业务员负责处理不同类型的故障报修,如何确保客户的维修请求能被正确处理?
            解决方案:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

#include <iostream>
#include <string>
#include <list>

class BaseHandler
{
private:
	BaseHandler* m_nextHandler;
public:
	BaseHandler* setNext(BaseHandler* handler)
	{
        m_nextHandler = handler;
        return m_nextHandler;
	}
	virtual std::string handle(std::string request)
	{
		if (m_nextHandler)
		{
			return m_nextHandler->handle(request);
		}
        return "";
	}

};

class RobotAI :public BaseHandler
{
public:
	std::string handle(std::string request) override
	{
		if (request == "使用向导")
		{
			return "RobotAI:我来处理"+request+"-。\n";
		}
		else
		{
			return BaseHandler::handle(request);
		}
	}
};

class TelOperator :public BaseHandler
{
public:
	std::string handle(std::string request) override
	{
		if (request == "常见问题")
		{
			return "TelOperator:我来处理" + request + "-。\n";
		}
		else
		{
			return BaseHandler::handle(request);
		}
	}
};

class Export :public BaseHandler
{
public:
	std::string handle(std::string request) override
	{
		if (request == "疑难杂症")
		{
			return "Export:我来处理" + request + "-。\n";
		}
		else
		{
			return BaseHandler::handle(request);
		}
	}
};

void client(BaseHandler& handler)
{
	std::list<std::string> requests = {"使用向导","常见问题","常见问题","疑难杂症","gahj"};
	for (const std::string& request : requests)
	{
		std::string result = handler.handle(request);
        std::cout << "Client:谁来处理" << request << std::endl;
		if (result.empty())
		{
			std::cout << "处理结果:无法处理请求:" << request << std::endl;
		}
		else
		{
            std::cout << "处理结果:" << result << std::endl;
		}
	}
}

int main()
{
	RobotAI robot;
	TelOperator tel;
	Export exp;
	robot.setNext(&tel)->setNext(&exp);
	std::cout << "Chain:机器人->话务员->专家" << std::endl;
	client(robot);

    return 0;
}

 二、与其他模式的关系

  • 责任链模式 (opens new window)、 命令模式 (opens new window)、 中介者模式 (opens new window)和观察者模式 (opens new window)用于处理请求发送者和接收者之间的不同连接方式:

    • 责任链按照顺序将请求动态传递给一系列的潜在接收者, 直至其中一名接收者对请求进行处理。
    • 命令在发送者和请求者之间建立单向连接。
    • 中介者清除了发送者和请求者之间的直接连接, 强制它们通过一个中介对象进行间接沟通。
    • 观察者允许接收者动态地订阅或取消接收请求。
  • 责任链 (opens new window)通常和组合模式 (opens new window)结合使用。 在这种情况下, 叶组件接收到请求后, 可以将请求沿包含全体父组件的链一直传递至对象树的底部。

  • 责任链 (opens new window)的管理者可使用命令模式 (opens new window)实现。 在这种情况下, 你可以对由请求代表的同一个上下文对象执行许多不同的操作。

    还有另外一种实现方式, 那就是请求自身就是一个命令对象。 在这种情况下, 你可以对由一系列不同上下文连接而成的链执行相同的操作。

  • 责任链 (opens new window)和装饰模式 (opens new window)的类结构非常相似。 两者都依赖递归组合将需要执行的操作传递给一系列对象。 但是, 两者有几点重要的不同之处。

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


http://www.niftyadmin.cn/n/5670292.html

相关文章

[Linux]:信号(下)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;Linux学习 贝蒂的主页&#xff1a;Betty’s blog 1. 信号的阻塞 1.1 基本概念 信号被操作系统发送给进程之后&#xff0c;进程…

基于SpringBoot+Vue+MySQL的国产动漫网站

系统展示 用户前台界面 管理员后台界面 系统背景 随着国内动漫产业的蓬勃发展和互联网技术的快速进步&#xff0c;动漫爱好者们对高质量、个性化的国产动漫内容需求日益增长。然而&#xff0c;市场上现有的动漫平台大多以国外动漫为主&#xff0c;对国产动漫的推广和展示存在不…

Linux提升篇-服务器BIOS介绍

目录 前言BIOS 概述常用配置进入 BIOS 界面查询 iBMCIP 地址设置 BIOS 系统日期和时间设置服务器启动方式 前言 以下bios介绍适用于大部分2020年之后的服务器&#xff0c;包括Huawei系的鲲鹏CPU架构服务器&#xff0c;X86系也可参考&#xff0c;大部分配置项是一致的。 BIOS …

linux cat命令的实现

cat 是 Linux 和其他 Unix-like 系统中的一个常用命令&#xff0c;它的名称来源于 "concatenate"&#xff08;连接&#xff09;的缩写。cat 命令主要用于查看、创建和拼接文件。它读取一个或多个文件的内容&#xff0c;并将它们显示在标准输出&#xff08;通常是终端…

富格林:积攒经验阻挠欺诈套路

富格林指出&#xff0c;现货黄金这些年可谓是表现出色&#xff0c;相信上车现货黄金的投资者&#xff0c;都或多或少分得一杯满意的羹。不过话又说回来&#xff0c;不是所有投资者都可以轻松在现货黄金中获利&#xff0c;尤其是对投资小白而言&#xff0c;如果没有积累知识阻挠…

jekyll相关的技术点

jekyll相关的技术点 1. gem bundle jekyll 三者的关系gembundleJekyll 2. jekyll命令3. 注意事项 如果你用过github的Pages功能(现在在Action功能中)&#xff0c;或者gitee中的Pages&#xff0c;那么对于jekyll你一定不陌生。今天研究部署了一下&#xff0c;供参考 1. gem bund…

(11)(2.1.2) DShot ESCs(二)

文章目录 前言 3 配置伺服功能 4 检查RC横幅 5 参数说明 前言 DShot 是一种数字 ESC 协议&#xff0c;它允许快速、高分辨率的数字通信&#xff0c;可以改善飞行器控制&#xff0c;这在多旋翼和 quadplane 应用中特别有用。 3 配置伺服功能 如上所述&#xff0c;如果使用…

谷歌的AI反击战:创始人谢尔盖·布林的回归与大模型组合的未来

近年来&#xff0c;随着AI技术的迅猛发展&#xff0c;尤其是ChatGPT等大语言模型的出现&#xff0c;全球科技格局正发生剧烈变化。作为曾经引领AI潮流的谷歌&#xff0c;在这场竞争中逐渐失去了领头羊的地位。然而&#xff0c;谷歌的创始人之一谢尔盖布林&#xff08;Sergey Br…