第24章 加薪非要老总批--责任链模式
24.1 老板,我要加薪!
今天小菜向经理提加薪申请,经理没权利,然后向总监上报,总监也没有权利,向总经理上报。其实这个就是一个责任链了。
24.2 加薪代码初步
#pragma once
#include "Request.h"
#include <iostream>
class Manager
{
public:
typedef enum _TypeManager
{
eManager,
eMajordomo,
eMasterManager
}TypeManagerLevel;
Manager(std::string str)
{
m_name = str;
};
void GetResult(TypeManagerLevel level, Request* req)
{
if (level == eManager)//经理
{
if (req->GetRequestType() == Request::eLeave && req->GetRequestNumber() <= 2)
{
std::cout << m_name << ":"
<< req->GetRequestContent()
<< "悢検" << req->GetRequestNumber()
<< "嫋壜偡傞" << std::endl;
}
else
{
std::cout << m_name << ":"
<< req->GetRequestContent()
<< "请假" << req->GetRequestNumber()
<< "请假被批准" << std::endl;
}
}
else if (level == eMajordomo)//总监
{
if (req->GetRequestType() == Request::eLeave && req->GetRequestNumber() <= 5)
{
std::cout << m_name << ":"
<< req->GetRequestContent()
<< "请假" << req->GetRequestNumber()
<< "请假被批准" << std::endl;
}
else
{
std::cout << m_name << ":"
<< req->GetRequestContent()
<< "请假" << req->GetRequestNumber()
<< "我无权处理" << std::endl;
}
}
else if (level == eMasterManager)//总经理
{
if (req->GetRequestType() == Request::eLeave)
{
std::cout << m_name << ":"
<< req->GetRequestContent()
<< "请假" << req->GetRequestNumber()
<< "请假被批准" << std::endl;
}
else if ( req->GetRequestType() == Request::eRaises && req->GetRequestNumber() <= 500 )
{
std::cout << m_name << ":"
<< req->GetRequestContent()
<< "加薪" << req->GetRequestNumber()
<< "加薪被批准" << std::endl;
}
else if ( req->GetRequestType() == Request::eRaises && req->GetRequestNumber() > 500 )
{
std::cout << m_name << ":"
<< req->GetRequestContent()
<< "加薪" << req->GetRequestNumber()
<< "加薪数量再说吧" << std::endl;
}
}
};
protected:
std::string m_name;
};
#pragma once
#include <string>
class Request
{
public:
typedef enum _TypeRequest
{
eLeave, //离职
eRaises //涨薪水
}TypeRequest;
public:
void SetRequestType(TypeRequest type)
{
m_RequestType = type;
};
void SetRequestContent(std::string str)
{
m_RequestContent =str;
};
void SetRequestNumber(int num)
{
m_Number = num;
};
TypeRequest GetRequestType(void)
{
return m_RequestType;
};
std::string GetRequestContent(void)
{
return m_RequestContent;
};
int GetRequestNumber(void)
{
return m_Number;
};
private:
//要求的类型
TypeRequest m_RequestType;
//要求的内容
std::string m_RequestContent;
//要求的数量
int m_Number;
};
客户端
// DesignPattern24.2.cpp : 僐儞僜乕儖 傾僾儕働乕僔儑儞偺僄儞僩儕 億僀儞僩傪掕媊偟傑偡丅
//
#include "stdafx.h"
#include "Manager.h"
int _tmain(int argc, _TCHAR* argv[])
{
//三个管理者
Manager* jinli = new Manager("jinli");
Manager* zongjian = new Manager("zongjian");
Manager* zongjinli = new Manager("zongjinli");
Request* requset = new Request();
requset->SetRequestType(Request::eRaises);
requset->SetRequestContent("小菜要求加薪.");
requset->SetRequestNumber(1000);
//不同级别对此进行的反馈
jinli->GetResult(Manager::eManager, requset);
zongjian->GetResult(Manager::eMajordomo, requset);
zongjinli->GetResult(Manager::eMasterManager, requset);
Request* requset2 = new Request();
requset2->SetRequestType(Request::eLeave);
requset2->SetRequestContent("小菜要请假.");
requset2->SetRequestNumber(3);
jinli->GetResult(Manager::eManager, requset2);
zongjian->GetResult(Manager::eMajordomo, requset2);
zongjinli->GetResult(Manager::eMasterManager, requset2);
delete jinli;
delete zongjian;
delete zongjinli;
delete requset2;
delete requset;
return 0;
}
经理,总监,总经理都是管理者,他们在对申请处理时,需要做出判断。其实这样做并不好,那个管理者类中,里面的"结果"方法比较长,加上有太多的分支判断,这其实是非常不好的设计。这个"管理者"类承担了太多的责任,这违背了单一职责原则,因为如果增加新的管理类别,就需要修改这个类了。也违背了开放-封闭原则。
24.3 职责链模式
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。这里发出这个请求的客户端并不知道这当中的哪一个对象最终处理这个请求,这样系统的更改可以在不影响客户端的情况下动态地重新组织和分配责任。
#pragma once
#include <iostream>
class Handler
{
public:
//设置继任者
void SetSuccessor(Handler* p)
{
this->m_successor = p;
};
//处理请求的抽象方法
virtual void HandlerRequest(int req) = 0;
virtual ~Handler(){};
protected:
Handler* m_successor;
};
class ConcreteHandler1 : public Handler
{
void HandlerRequest(int req)
{
if (req >= 0 && req < 10)
{
std::cout << "ConcreteHandler1:处理请求"
<< req << std::endl;
}
else if (m_successor != NULL)
{//转移到下一位
m_successor->HandlerRequest(req);
}
};
};
class ConcreteHandler2 : public Handler
{
void HandlerRequest(int req)
{
if (req >= 10 && req < 20)
{
std::cout << "ConcreteHandler2:处理请求"
<< req << std::endl;
}
else if (m_successor != NULL)
{//转移到下一位
m_successor->HandlerRequest(req);
}
};
};
class ConcreteHandler3 : public Handler
{
void HandlerRequest(int req)
{
if (req >= 20 && req < 30)
{
std::cout << "ConcreteHandler3:处理请求"
<< req << std::endl;
}
else if (m_successor != NULL)
{//转移到下一位
m_successor->HandlerRequest(req);
}
};
};
Handler类,定义一个处理请示的接口。
ConcreteHandler类,具体处理着类,处理它所负责的请求,可访问它的后继者,如果可处理该请求,就处理之,否这就将该请求转发给它的后继者。
ConcreteHandler1类:当请求数在0到10之间则有权处理,否则转到下一位。
ConcreteHandler2类:当请求数在10到20之间则有权处理,否则转到下一位。
ConcreteHandler3类:当请求数在20到30之间则有权处理,否则转到下一位。
客户端程序
// DesignPattern24.3.cpp
#include "stdafx.h"
#include "Handle.h"
int _tmain(int argc, _TCHAR* argv[])
{
Handler* h1 = new ConcreteHandler1();
Handler* h2 = new ConcreteHandler2();
Handler* h3 = new ConcreteHandler3();
//设置责任链的上家和下家
h1->SetSuccessor(h2);
h2->SetSuccessor(h3);
int requests[] = {2, 5, 14, 22, 18, 3, 27, 20 };
for ( int i = 0; i < _countof(requests); i++ )
{
h1->HandlerRequest(requests[i]);
}
delete h1;
delete h2;
delete h3;
return 0;
}
24.4 职责链的好处
当客户提交一个请求时,请求是沿链传递直至有一个ConcreteHandler对象负责处理它。这样做的好处就是请求者不用去管哪个对象来处理请求了。
接收者和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅需要保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用,这样就大大降低了耦合度了。但也有一种可能,一个请求极有可能到了链的末端都得不到处理,或者因为没有正确配置而得不到处理。回到24.2的例子,其实写的管理者类当中的那些分支,分解到每一个具体的管理者类当中,然后利用事先设置的后继者来实现请求处理的权限问题。
24.5 加薪代码重构
#pragma once
#include "Request.h"
#include <iostream>
//管理者
class Manager
{
public:
Manager(Manager* p)
{
m_pManager = p;
};
Manager(std::string str)
{
m_Name = str;
};
void SetManagers(Manager* p)
{
m_pManager = p;
}
virtual void RequestAppcation(Request* req) = 0;
virtual ~Manager(){};
protected:
std::string m_Name;
//管理者的上级
Manager* m_pManager;
};
//经理
class CommonManager :public Manager
{
public:
CommonManager(std::string str)
:Manager(str)
{
};
void RequestAppcation(Request* req)
{
if ( req->GetRequestType() == Request::eLeave )
{
std::cout << m_Name << ":"
<< req->GetRequestContent()
<< "请假" << req->GetRequestNumber()
<< "被批准" << std::endl;
}
else
{
if ( m_pManager != NULL )
{
m_pManager->RequestAppcation(req);
}
}
};
};
//总监
class Majordomo :public Manager
{
public:
Majordomo(std::string str)
:Manager(str)
{
};
void RequestAppcation(Request* req)
{
if ( req->GetRequestType() == Request::eLeave && req->GetRequestNumber() < 5 )
{
std::cout << m_Name << ":"
<< req->GetRequestContent()
<< "请假" << req->GetRequestNumber()
<< "被批准" << std::endl;
}
else
{
if ( m_pManager != NULL )
{
m_pManager->RequestAppcation(req);
}
}
};
};
//总经理
class GeneralManager :public Manager
{
public:
GeneralManager(std::string str)
:Manager(str)
{
};
void RequestAppcation(Request* req)
{
if ( req->GetRequestType() == Request::eLeave )
{
std::cout << m_Name << ":"
<< req->GetRequestContent()
<< "请假" << req->GetRequestNumber()
<< "被批准" << std::endl;
}
else if ( req->GetRequestType() == Request::eRaises && req->GetRequestNumber() <= 500 )
{
std::cout << m_Name << ":"
<< req->GetRequestContent()
<< "加薪" << req->GetRequestNumber()
<< "被批准" << std::endl;
}
else if ( req->GetRequestType() == Request::eRaises && req->GetRequestNumber() > 500 )
{
std::cout << m_Name << ":"
<< req->GetRequestContent()
<< "加薪" << req->GetRequestNumber()
<< "不被批准" << std::endl;
}
else
{
if ( m_pManager != NULL )
{
m_pManager->RequestAppcation(req);
}
}
};
};
我们把原来的一个"管理者"类改成了一个抽象类和三个具体类,此时类之间的灵活性就大大增加了,如果我们需要扩展新的管理者类别,只需要增加子类就可以了。
24.6 加薪成功
小菜加薪成功.