软件在运行时出了问题,需要解决的时候,是不是会出现下述这种很头痛的情况。比如,前端网页无法加载显示图片了,这个问题去找前端的同事处理,前端的同事看了下,说不是他的问题,是中间件传输过来的数据有问题;又找中间件的同事去看,中间件的同事说,是后端java那块发送过来的数据有问题;又去找java开发的同事,java开发的同事说,数据库表结构损坏导致出了问题;又去找数据库的同事解决问题,最终数据库的同事看了下,确实是表结构损坏导致了该问题,然后数据库同事解决了该问题,之后前端网页就可以正常显示图片了。当然这是一种最糟糕的情况,也许在中间环节的同事就判断是他那边的问题,他解决后,最终的问题解决了。
软件出现问题,这种处理关系是一种链状的形式。每个对象决定该问题是自己处理还是交由下个对象处理。如果在一个类中用if/else来处理这种关系,那么当C++开发参与到这个流程中时,就需要修改这个类的代码了,这样不符合开放封闭原则。如何设计程序能够处理这种链状关系,且当这个链中插入新的环节时,不用修改类的代码?
Chain.h
在该文件中,实现了这个链的环节的处理者的基类CBaseHandler,以及他的子类CWebDeveloper(Web前端开发人员)、CMiddlewareDeveloper(中间件开发人员)、CJavaDeveloper(Java开发人员)、CDBDeveloper(数据库开发人员)。
通过CBaseHandler的SetSuccessor函数来确认下个环节的处理人员,这样可以由客户程序灵活搭配整个链结构。
#pragma once
#include
//链的环节处理者基类
class CBaseHandler
{
public:
CBaseHandler():
m_pSuccessor(nullptr)
{
}
virtual ~CBaseHandler()
{
}
//处理问题
virtual void DealProblem(int iData) = 0;
//设置下个环节
void SetSuccessor(CBaseHandler* pSuccessor)
{
if (nullptr != pSuccessor)
{
m_pSuccessor = pSuccessor;
}
}
CBaseHandler* m_pSuccessor;
};
//Web前端开发人员
class CWebDeveloper : public CBaseHandler
{
public:
CWebDeveloper()
{
}
virtual ~CWebDeveloper()
{
}
void DealProblem(int iData)
{
if (iData > 0 && iData <= 10)
{
std::cout << "这个问题是前端的问题,我去搞定它" << std::endl;
}
else
{
if (nullptr != m_pSuccessor)
{
m_pSuccessor->DealProblem(iData);
}
}
}
};
//中间件开发人员
class CMiddlewareDeveloper : public CBaseHandler
{
public:
CMiddlewareDeveloper()
{
}
virtual ~CMiddlewareDeveloper()
{
}
void DealProblem(int iData)
{
if (iData > 10 && iData <= 20)
{
std::cout << "这个问题是中间件的问题,我去搞定它" << std::endl;
}
else
{
if (nullptr != m_pSuccessor)
{
m_pSuccessor->DealProblem(iData);
}
}
}
};
//Java开发人员
class CJavaDeveloper :public CBaseHandler
{
public:
CJavaDeveloper()
{
}
virtual ~CJavaDeveloper()
{
}
void DealProblem(int iData)
{
if (iData > 20 && iData <= 30)
{
std::cout << "这个问题是java后端的问题,我去搞定它" << std::endl;
}
else
{
if (nullptr != m_pSuccessor)
{
m_pSuccessor->DealProblem(iData);
}
}
}
};
//数据库开发人员
class CDBDeveloper : public CBaseHandler
{
public:
CDBDeveloper()
{
}
virtual ~CDBDeveloper()
{
}
void DealProblem(int iData)
{
if (iData > 30 && iData <= 40)
{
std::cout << "这个问题是数据库的问题,我去搞定它" << std::endl;
}
else
{
if (nullptr != m_pSuccessor)
{
m_pSuccessor->DealProblem(iData);
}
}
}
};
main.cpp
// main.cpp : 定义控制台应用程序的入口点。
//
#include "Chain.h"
int main()
{
CBaseHandler* pWebDeveloper = new(std::nothrow) CWebDeveloper();
CBaseHandler* pMiddlewareDeveloper = new(std::nothrow) CMiddlewareDeveloper();
CBaseHandler* pJavaDeveloper = new(std::nothrow) CJavaDeveloper();
CBaseHandler* pDBDeveloper = new(std::nothrow) CDBDeveloper();
//设置链结构
pWebDeveloper->SetSuccessor(pMiddlewareDeveloper);
pMiddlewareDeveloper->SetSuccessor(pJavaDeveloper);
pJavaDeveloper->SetSuccessor(pDBDeveloper);
int iArrayProblem[] = { 2, 4, 33, 12 ,23 };
for (auto Data : iArrayProblem)
{
pWebDeveloper->DealProblem(Data);
}
if (nullptr != pWebDeveloper)
{
delete pWebDeveloper;
pWebDeveloper = nullptr;
}
if (nullptr != pMiddlewareDeveloper)
{
delete pMiddlewareDeveloper;
pMiddlewareDeveloper = nullptr;
}
if (nullptr != pJavaDeveloper)
{
delete pJavaDeveloper;
pJavaDeveloper = nullptr;
}
if (nullptr != pDBDeveloper)
{
delete pDBDeveloper;
pDBDeveloper = nullptr;
}
system("pause");
return 0;
}
运行结果:
职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
职责链模式的关键是当客户提交一个请求时,请求是沿链传递直至有一个具体对象负责处理它。这样使得接受者和发送者都没有对方的明确信息,且链中的对象自己也不知道链的结构,结果是职责链可简化对象的互相连接,它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选者的引用。这也就大大降低了耦合度。
由于是客户来定义链的结构,可随时地增加或者修改处理一个请求的结构。增强了给对象指派职责的灵活性。如在示例程序中,如果要在处理问题的链结构中插入一个C++开发人员,则只需要再增加一个C++开发人员的子类,然后由客户程序修改设置链结构的地方即可。但是需要注意这样配置虽然很灵活,不过需要当心——一个请求极有可能到了链的末端都得不到处理,或者因为没有正确配置而得不到处理,这就很糟糕了。需要事先考虑全面。
职责链模式最重要需要关注的两点:
1)为每个对象设置后继者
2)每个对象处理时,需做出判断,是可以处理这个请求,还是必须要“推卸责任”,转移给后继者去处理。
当一个请求是沿链传递,链的每一个环节都有可能处理它。
返回目录:设计模式(C++实现)(总)
上一篇:设计模式(C++实现)(二十)——命令模式
下一篇:设计模式(C++实现)(二十二)——中介者模式