责任链模式(职责链模式)
当我学习了责任链模式,准备进行写作分享的时候,我觉得拿魔塔这个游戏进行举例说明可能比较贴近,魔塔里面每10层有一个boss,而这个boss的属性可能从一开始的问号到明确数值。当你被打败后,会被嘲讽两句,然后你会去刷装备、刷等级、刷属性、氪金变强等等,然后打败了第一个boss,会继续重复这个流程,只是每个boss属性值变化罢了。这就可以抽象为责任链模式:以某个数值或者某个标准作为分类规则,将一系列的对象形成一个链条,处理请求时,一层层向上传输,直到某个节点可以处理这个请求。
基础uml图:
抽象处理者Handle:用于存储责任链的下一个节点、节点设置函数、外加一个抽象的目的函数,做到共同点的集中化。
具体处理者ConcreteHandler:具体的处理类,其中通过一定的标准,来判断是否在该类处理,不能就通过基类所存储的下一节点对象进行传递处理
使用场景:
- 当一个逻辑有很多判断分支的时候,过多的if会使得不易修改和不易拓展
- 当一个请求涉及到多个对象使用的时候,用该模式找到确定的对象
- 当未指定确定的对象并且涉及到多对象的时候,通过该模式找到最适合的处理函数
优点:
- 降低了代码的耦合度。每个类负责自己所需要负责的区间
- 简化了对象。对象只记录下一节点的对象,不需要整条链的结构。
- 易于拓展。对于链条的节点增删变化、其中的功能修改都简单化了。
缺点:
- 如果分类不够精准,可能导致一些情况下不能被响应
实操
UML
责任:每个或者说是整个程序都是为了解决一类的问题。 比如打boss、升职、加薪、投简历等等,都是实际上需要一层层向上找负责人的过程。
链:你的请求一层层向上传输的时候,每个节点不需要知道整体,只需要知道我的上一层在哪里就行了,也可能是下层在哪里。其原理和单链表差不多。
思维顺序:
- 指定一个问题的分类规则和分类。比如我分为10、100、1000,这就是标准,然后用继承派生写出整个类组,抽象处理函数和具体的处理函数
- 添加一个基类指针。作为一个节点的上层boss对象
- 由于已经存在上层了,所以处理函数不可能直接进行处理了,因此需要添加判断函数,满足条件就自己处理,不满足就向上传递
// ChainOfResponsibilitModel.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
using namespace std;
#define interface struct
interface IBoss
{
protected:
IBoss* m_leader;
public:
void SetLeader(IBoss* leader) { m_leader = leader; }
virtual void FightNewBoss(int power) = 0;
};
class CBoss1 : public IBoss
{
public:
void FightNewBoss(int power)
{
if (10 >= power)
{
cout << "小菜鸡,你打不赢我的,战力10都没有达到,滚回去充钱吧。" << endl;
}
else if (NULL != m_leader)
{
cout << "贤者:勇士啊,快去迎接你的下一个boss吧,战力100,你先充钱再去试试吧。" << endl;
m_leader->FightNewBoss(power);
}
}
};
class CBoss2 : public IBoss
{
void FightNewBoss(int power)
{
if (100 >= power)
{
cout << "小菜鸡,你打不赢我的,战力100都没有达到,滚回去充钱吧。" << endl;
}
else if(NULL != m_leader)
{
cout << "贤者:勇士啊,快去迎接你的下一个boss吧,战力1000,你先充钱再去试试吧。" << endl;
m_leader->FightNewBoss(power);
}
}
};
class CBoss3 : public IBoss
{
void FightNewBoss(int power)
{
if (1000 >= power)
{
cout << "小菜鸡,你打不赢我的,战力1000都没有达到,滚回去充钱吧。" << endl;
}
else
{
cout << "贤者:你通关了,给你一片田,收菜去吧!" << endl;
//m_leader->FightNewBoss(power);
}
}
};
int main()
{
IBoss* boss1 = new CBoss1();
IBoss* boss2 = new CBoss2();
IBoss* boss3 = new CBoss3();
boss1->SetLeader(boss2);
boss2->SetLeader(boss3);
cout << "战力为8的勇士来到了boss面前。" << endl;
boss1->FightNewBoss(8);
cout << "============================" << endl;
cout << "战力为18的勇士来到了boss面前。" << endl;
boss1->FightNewBoss(18);
cout << "============================" << endl;
cout << "战力为108的勇士来到了boss面前。" << endl;
boss1->FightNewBoss(108);
cout << "============================" << endl;
cout << "战力为1008的勇士来到了boss面前。" << endl;
boss1->FightNewBoss(1008);
}