责任链模式
什么是责任链模式
责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。比如有三个项目经理,顺序是A->B->C,把所有的项目都先传递给A,A拿到所有的项目后,把属于自己负责的项目留下来,把剩下的传递给B,然后B把属于自己的留下来,把不属于自己的再传递给C。
为什么使用责任链模式
该模式能将多个处理者连接成一条链。 接收到请求后, 它会 “询问” 每个处理者是否能够对其进行处理。 这样所有处理者都有机会来处理请求。 无论你以何种顺序将处理者连接成一条链, 所有请求都会严格按照顺序通过链上的处理者。如果在处理者类中有对引用成员变量的设定方法, 你将能动态地插入和移除处理者, 或者改变其顺序。总的来说链条式处理事情。工作流程化、消息处理流程化、事物流程化。
责任链模式实现步骤
1.提供处理类的抽象父类:抽象客户端如何将请求数据传递给方法
2.依次创建具体处理者子类并实现其处理方法
-
是否自行处理这个请求
-
是否将该请求沿着链进行传递
3.客户端处理链(组装链+触发处理者),客户端需要准备好处理以下情况:
缺点
-
链中可能只有单个链接
-
部分请求可能无法到达链尾
-
其他请求可能直到链尾都未被处理
//莫影请假 #include <iostream> using namespace std; class Handler { public: Handler() : pnext(nullptr) {} void SetNextHandler(Handler* pnext) { this->pnext = pnext; } virtual void HandleRequest(int days) = 0; protected: Handler* pnext; }; class Director : public Handler { public: virtual void HandleRequest(int days) { cout << "主管:"; if (days <= 1) { cout << "有权批准一天假,同意" << endl; } else { cout << "请假太长,转接经理" << endl; pnext->HandleRequest(days); } } }; class Manager : public Handler { public: virtual void HandleRequest(int days) { cout << "经理:"; if (days <= 3) { cout << "有权批准三天假,同意" << endl; } else { cout << "请假太长,转接老板!" << endl; pnext->HandleRequest(days); } } }; class Boss : public Handler { public: virtual void HandleRequest(int days) { cout << "老板:"; if (days <= 7) { cout << "7天之内,同意" << endl; } else { cout << "请假时间天长,不同意" << endl; } } }; int main() { Handler* director = new Director; Handler* manager = new Manager; Handler* boss = new Boss; director->SetNextHandler(manager); manager->SetNextHandler(boss); cout << "请假7天:" << endl; director->HandleRequest(7); return 0; }
责任链模式优缺点
优点
-
你可以控制请求处理的顺序
-
单一职责原则: 你可对发起操作和执行操作的类进行解耦
-
部分请求可能未被处理
-
开闭原则:你可以在不更改现有代码的情况下在程序中新增处理者
-
策略模式
什么是策略模式
策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换
为什么使用策略模式
策略模式让你能够将对象关联至可以不同方式执行特定子任务的不同子对象, 从而以间接方式在运行时更改对象行为。策略模式让你能将不同行为抽取到一个独立类层次结构中, 并将原始类组合成同一个, 从而减少重复代码。策略模式让你能将各种算法的代码、 内部数据和依赖关系与其他代码隔离开来。 不同客户端可通过一个简单接口执行算法, 并能在运行时进行切换。策略模式将所有继承自同样接口的算法抽取到独立类中, 因此不再需要条件语句。 原始对象并不实现所有算法的变体, 而是将执行工作委派给其中的一个独立算法对象。从而解决在同一算法的不同变体中切换时避免使用多重条件判断。
策略模式实现步骤
1.提供一个抽象策略类:定义抽象的函数算法让继承的子类实现
2.提供具体策略类:封装了继续相关的算法和行为,即函数的具体功能的实现
3.提供一个策略的容器类:根据不同策略执行不同的行为,策略由外部 环境决定
//简单计算器
#include <iostream>
using namespace std;
class Strategy {
public:
virtual int Execute(int left, int right) = 0;
};
class Add : public Strategy {
public:
int Execute(int left, int right) { return left + right; }
};
class Sub : public Strategy {
public:
int Execute(int left, int right) { return left - right; }
};
class Mul : public Strategy {
public:
int Execute(int left, int right) { return left * right; }
};
class Div : public Strategy {
public:
int Execute(int left, int right) { return left / right; }
};
class Context {
public:
void SetStrategy(Strategy* ps) { this->ps = ps; }
int ExecuteStrategy(int left, int right) {
return ps->Execute(left, right);
}
private:
Strategy* ps;
};
int main() {
Context* pcontext = new Context;
int left, right;
char key;
while (1) {
cin >> left >> key >> right;
switch (key) {
case '+':
pcontext->SetStrategy(new Add);
break;
case '-':
pcontext->SetStrategy(new Sub);
break;
case '*':
pcontext->SetStrategy(new Mul);
break;
case '/':
pcontext->SetStrategy(new Div);
break;
}
cout << pcontext->ExecuteStrategy(left, right) << endl;
}
return 0;
}
策略模式优缺点
优点
-
你可以在运行时切换对象内的算法
-
你可以将算法的实现和使用算法的代码隔离开来
-
你可以使用组合来代替继承
-
开闭原则:你无需对上下文进行修改就能够引入新的策略
缺点
-
如果你的算法极少发生改变, 那么没有任何理由引入新的类和接口。 使用该模式只会让程序过于复杂
-
客户端必须知晓策略间的不同——它需要选择合适的策略
-
借助额外的类和接口可能会让代码不够简洁