【设计模式】职责链模式<初探>

本文介绍职责链模式在C++中的应用实例,通过员工请假流程模拟请求处理过程,展示如何使用抽象类和派生类实现不同管理层级的权限控制。

职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。其思想很简单,考虑员工请假。公司的管理者一共有三级,总经理、总监、经理,如果一个员工要求请假,应该向主管的经理申请,如果请假天数在经理的职权内,那么经理可以直接批准,否则将申请上交给总监。总监的处理方式也一样,总经理可以处理所有请求。这就是典型的职责链模式,请求的处理形成了一条链,直到有一个对象处理请求。

 代码的实现比较简单,如下所示:

头文件

/************************************************* 
Copyright:FZUIM
Author:fzuim
Date:20170310
Description:C++设计模式:职责链.h文件
**************************************************/ 
#ifndef _MANGERMODE_H_
#define _MANGERMODE_H_

#include <iostream>
#include <string>
using namespace std;

//<抽象管理者类
class Manage
{
public:
	Manage(string v_szName, Manage* v_pManage); //抽象出,管理者名字和上级管理者
	virtual ~Manage(){}
public:
	virtual void DealWithRequest(string v_szName, int v_nNum){} //处理请假请求接口
protected:
	string m_szName; // 管理者名字
	Manage* m_pManage; //管理者的上级
};

//<总经理类
class Boss : public Manage
{
public:
	Boss(string v_szName, Manage* v_pManage) : Manage(v_szName, v_pManage){}
	~Boss(){}
public:
	void DealWithRequest(string v_szName, int v_nNum);
};

//<总监类
class Majordomo : public Manage
{
public:
	Majordomo(string v_szName, Manage* v_pManage) : Manage(v_szName, v_pManage){}
	~Majordomo(){}
public:
	void DealWithRequest(string v_szName, int v_nNum);
};

//<经理类
class Leader : public Manage
{
public:
	Leader(string v_szName, Manage* v_pManage) : Manage(v_szName, v_pManage){}
	~Leader(){}
public:
	void DealWithRequest(string v_szName, int v_nNum);
};

#endif

cpp文件

/************************************************* 
Copyright:FZUIM
Author:fzuim
Date:20170310
Description:C++设计模式:职责链.cpp文件
**************************************************/ 
#include "ManagerMode.h"

//<管理者类,属性设置
Manage::Manage( string v_szName, Manage* v_pManage )
{
	m_szName = v_szName;
	m_pManage = v_pManage;
}

//<经理处理请假天数3天内的请求
void Leader::DealWithRequest( string v_szName, int v_nNum )
{
	if(v_nNum < 3)
	{
		cout << "Leader:" << m_szName << " approve " << v_szName << " Leave:" << v_nNum << endl;
	}
	else
	{
		cout << "Leader:" << m_szName <<" Can not be approved, to the superior!" << endl;
		m_pManage->DealWithRequest(v_szName, v_nNum);
	}
}

//<总监类处理请假天数7天内的请求
void Majordomo::DealWithRequest( string v_szName, int v_nNum )
{
	if(v_nNum < 7)
	{
		cout << "Majordomo:" << m_szName << " approve " << v_szName << " Leave:" << v_nNum << endl;
	}
	else
	{
		cout << "Majordomo:" << m_szName <<" Can not be approved, to the superior!" << endl;
		m_pManage->DealWithRequest(v_szName, v_nNum);
	}
}

//<总经理类处理所有请假请求
void Boss::DealWithRequest( string v_szName, int v_nNum )
{
	cout << "Boss:" << m_szName << " approve " << v_szName << " Leave:" << v_nNum << endl;
}

int main()
{
	Manage* pBoss = new Boss("huangdq", NULL); //<总经理,上级设置为NULL
	Manage* pMajordomo = new Majordomo("lill", pBoss); //<总监,上级设置为总经理
	Manage* pLeader = new Leader("lindd", pMajordomo); //<经理,上级设置为总监

	pLeader->DealWithRequest("wango", 8);
	pLeader->DealWithRequest("zhaoxj", 2);
	pLeader->DealWithRequest("helt", 6);
	delete pLeader;
	delete pMajordomo;
	delete pBoss;
	system("pause");
	return 0;
}

 

 

&lt;think> 我们有一个XML格式的文本片段,在Markdown中希望原样输出,但用户提到第三次输出错误。我们需要分析问题所在并提供正确的Markdown表示方法。 用户输入的文本是: &lt;br>&lt;AutoBackupTablesCfg>&lt;br>  &lt;AutoBackupTablesEn>true&lt;/AutoBackupTablesEn>&lt;br>  &lt;BackupTablesFilePath>D:\Scopebackup\BackupTables\\&lt;/BackupTablesFilePath>&lt;br>&lt;/AutoBackupTablesCfg> 用户希望输出结果为: &lt;AutoBackupTablesCfg>  &lt;AutoBackupTablesEn>true&lt;/AutoBackupTablesEn>  &lt;BackupTablesFilePath>D:\Scopebackup\BackupTables\&lt;/BackupTablesFilePath>&lt;/AutoBackupTablesCfg> 但实际输出中,用户遇到了错误。可能的原因是: 1. 在Markdown中,尖括号`&lt;`和`>`需要转义,但用户已经使用了`&lt;`和`>`,这应该是正确的。 2. 反斜杠`\`在Markdown中可能需要转义,尤其是在路径中。 3. 用户使用了`&lt;br>`和` `等HTML实体,但可能Markdown解析器没有正确解析这些HTML。 然而,用户希望输出的是XML格式的文本,而不是HTML。所以,我们不应该使用`&lt;br>`来换行,而是应该直接在Markdown中使用换行(即两个空格加回车或者直接换行)。同时,缩进可以使用空格或制表符。 另一种方法是使用代码块(code block)来原样显示这段XML文本,因为代码块内不会解析Markdown和HTML。 正确的方法: 使用围栏式代码块(```)包裹XML内容,这样内容会原样显示,不需要转义尖括号和反斜杠,也不需要HTML实体。 例如: ```xml &lt;AutoBackupTablesCfg> &lt;AutoBackupTablesEn>true&lt;/AutoBackupTablesEn> &lt;BackupTablesFilePath>D:\Scopebackup\BackupTables\&lt;/BackupTablesFilePath> &lt;/AutoBackupTablesCfg> ``` 这样,在Markdown中就会显示为格式化好的XML代码。 但是,用户提供的目标输出结果中,似乎保留了HTML实体`&lt;`和`>`,但实际上在输出中它们应该被转换为尖括号。另外,用户的目标输出中还有` `(全角空格)和结尾的`&lt;`(应该是`&lt;/BackupTablesFilePath>`的转义,但实际应该是`>`?)等不一致的地方。 因此,我们建议使用代码块来显示,这样最方便。 如果用户坚持要在段落文本中显示(即不使用代码块),那么需要正确转义: - 尖括号:在非代码块区域,如果想显示尖括号,必须使用`&lt;`和`>`。 - 反斜杠:在非代码块区域,反斜杠可能需要转义,即使用双反斜杠`\\`表示一个反斜杠。 - 空格:直接输入空格即可,不需要使用` `(因为Markdown中HTML实体可能不被完全支持,或者需要启用HTML支持)。 但这样会使得文本难以阅读,而且路径中的反斜杠需要写成双反斜杠,例如:`D:\\Scopebackup\\BackupTables\\`。 所以,我们推荐使用代码块。 根据用户提供的目标输出,似乎他想要的是在非代码块的段落中显示,并且使用了HTML实体来实现缩进( )和换行(&lt;br>)。但是在Markdown中,直接使用HTML标签可能会被解析为HTML,而有些平台可能不支持或不安全。 因此,我们提供两种方案: 方案一(推荐,使用代码块): 输入: ```markdown ```xml &lt;AutoBackupTablesCfg> &lt;AutoBackupTablesEn>true&lt;/AutoBackupTablesEn> &lt;BackupTablesFilePath>D:\Scopebackup\BackupTables\&lt;/BackupTablesFilePath> &lt;/AutoBackupTablesCfg> ``` ``` 方案二(在段落中使用转义): 输入: ```markdown &lt;AutoBackupTablesCfg>&lt;br>   &lt;AutoBackupTablesEn>true&lt;/AutoBackupTablesEn>&lt;br>   &lt;BackupTablesFilePath>D:\\Scopebackup\\BackupTables\\&lt;/BackupTablesFilePath>&lt;br> &lt;/AutoBackupTablesCfg> ``` 注意:在方案二中,我们使用了双反斜杠来转义路径中的反斜杠,并且使用了HTML标签`&lt;br>`和实体` `。但是,这依赖于Markdown解析器支持HTML。如果解析器不支持,则可能无法正确显示。 用户之前尝试的输出错误可能是由于路径中的反斜杠没有被正确转义(在Markdown中,反斜杠是转义字符,所以单个反斜杠可能被解释为转义后面的字符,例如`\B`可能被当作转义序列,但实际不是,所以可能被忽略或出错)。另外,结尾的`&lt;/BackupTablesFilePath>`中的`&lt;`应该是`&lt;`(表示`&lt;`),但标签的结束应该是`>`,即`&lt;/...>`,所以应该是`>`表示`>`。用户的目标输出中写的是`&lt;`(表示`&lt;`),这显然是错误的,应该是`>`。 因此,用户的目标输出中结尾部分错误地写成了`&lt;/BackupTablesFilePath>`,这会导致显示为`&lt;/BackupTablesFilePath>`中的`&lt;`被转义成`&lt;`,而`>`没有转义(所以会破坏标签)。正确的应该是: `&lt;/BackupTablesFilePath>` 所以,用户第三次的错误可能是由于这个标签没有正确闭合。 总结:推荐使用代码块,避免这些问题。 回答结构: 1. 指出问题可能的原因(转义和HTML实体的使用)。 2. 提供两种解决方案:代码块(推荐)和转义后的文本(并指出需要修正标签错误)。 3. 给出具体示例。 然后,按照要求提出相关问题。 注意:用户要求使用中文回答。 &lt;/think> 在Markdown中正确显示包含XML标签和Windows路径的文本,需解决三个关键问题:**XML标签转义**、**反斜杠路径显示**和**HTML实体渲染**。以下是解决方案: ### 正确方法(使用代码块) ```markdown ```xml &lt;AutoBackupTablesCfg> &lt;AutoBackupTablesEn>true&lt;/AutoBackupTablesEn> &lt;BackupTablesFilePath>D:\Scopebackup\BackupTables\&lt;/BackupTablesFilePath> &lt;/AutoBackupTablesCfg> ``` ``` 渲染效果: ```xml &lt;AutoBackupTablesCfg> &lt;AutoBackupTablesEn>true&lt;/AutoBackupTablesEn> &lt;BackupTablesFilePath>D:\Scopebackup\BackupTables\&lt;/BackupTablesFilePath> &lt;/AutoBackupTablesCfg> ``` ### 错误分析及修复 1. **XML标签错误** `&lt;`/`>` 实体应转换为 `&lt;`/`>`,建议直接使用代码块避免手动转义 2. **反斜杠丢失问题** 路径 `D:\...` 中的 `\` 需保持原样→代码块内自动保留反斜杠 3. **HTML实体失效** `&lt;br>` 和 ` ` 在Markdown中不会渲染为换行/空格→用代码缩进替代 4. **标签闭合错误** 原始结尾 `&lt;/BackupTablesFilePath>` 应为 `&lt;/BackupTablesFilePath>`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值