定义:
使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止
////////////////// ********** 3. 责任链模式(通用版),代码清单16-3:***************//
enum EType
{
EType1 = 1,
EType2 ,
EType3
};
class IRequest
{
public:
virtual EType getType() = 0;
virtual QString getRequest() = 0;
};
class Request:public IRequest
{
public:
Request(EType type, QString request)
{
this->m_type = type;
this->m_request = request;
}
virtual EType getType()
{
return this->m_type;
}
virtual QString getRequest()
{
return this->m_request;
}
private:
EType m_type;
QString m_request;
};
class Handler
{
public:
Handler(){}
Handler(EType type)
{
this->m_type = type;
}
void handleMessage(IRequest *request)
{
if (request->getType() == this->m_type)
{
this->response(request);
}
else
{
if (this->m_nextHandler != nullptr)
{
this->m_nextHandler->handleMessage(request);
}
else
{
qDebug() << "NO!";
}
}
}
void setNext(Handler *handler)
{
this->m_nextHandler = handler;
}
protected:
virtual void response(IRequest *request) = 0;
protected:
Handler *m_nextHandler;
EType m_type;
};
class ConcreteHandler1:public Handler
{
public:
ConcreteHandler1()
{
this->m_type = EType1;
}
protected:
virtual void response(IRequest *request)
{
qDebug() << "request:" << request->getRequest();
}
};
class ConcreteHandler2:public Handler
{
public:
ConcreteHandler2()
{
this->m_type = EType1;
}
protected:
virtual void response(IRequest *request)
{
qDebug() << "request:" << request->getRequest();
}
};
class ConcreteHandler3:public Handler
{
public:
ConcreteHandler3()
{
this->m_type = EType1;
}
protected:
virtual void response(IRequest *request)
{
qDebug() << "request:" << request->getRequest();
}
};
class Client
{
public:
Client()
{
QString strRequest = "***";
for (int i = 0; i < 5; ++i)
{
srand((unsigned)time(NULL));
int num = rand() % (4 - 1) + 1;
EType type = EType(num);
IRequest* request = new Request(type, strRequest);
m_requests.push_back(request);
}
}
void request()
{
Handler *handler1 = new ConcreteHandler1();
Handler *handler2 = new ConcreteHandler2();
Handler *handler3 = new ConcreteHandler3();
handler1->setNext(handler2);
handler2->setNext(handler3);
QList::ConstIterator iter = m_requests.begin();
while(iter != m_requests.end())
{
IRequest* request = *iter;
if (request->getType() == EType1)
{
handler1->handleMessage(request);
}
else if (request->getType() == EType2)
{
handler2->handleMessage(request);
}
else if (request->getType() == EType3)
{
handler3->handleMessage(request);
}
else{}
++iter;
}
}
private:
QList m_requests;
};
int main()
{
Client client;
client.request();
return 0;
}
妇女出门,出嫁前请示父亲,出嫁后请示丈夫,丈夫不在请示儿子
IHandler 是三个有决策权对象的接口, IWomen 是女性的代码
//////////////// ********** 1. 妇女“三从”初始设计,代码清单16-1:***************//
enum EType
{
ENotMarry = 1,
EMarry ,
ENothusband
};
class IWomen
{
public:
virtual int getType() = 0; //获得个人状况
virtual QString getRequest() = 0; //获得个人请示
};
class Women:public IWomen
{
public:
Women(EType type, QString request)
{
this->m_type = type;
this->m_request = request;
}
virtual int getType()
{
return this->m_type;
}
virtual QString getRequest()
{
return this->m_request;
}
private:
int m_type;
QString m_request;
};
class IHandler
{
public:
virtual void HandleMessage(IWomen *women) = 0;
};
class Father:public IHandler
{
public:
virtual void HandleMessage(IWomen *women)
{
qDebug() << "request:" << women->getRequest();
qDebug() << "Father restore: ...";
}
};
class Husband:public IHandler
{
public:
virtual void HandleMessage(IWomen *women)
{
qDebug() << "request: "<< women->getRequest();
qDebug() << "Husband restore: ...";
}
};
class Son:public IHandler
{
public:
virtual void HandleMessage(IWomen *women)
{
qDebug() << "request: "<< women->getRequest();
qDebug() << "Son restore: ...";
}
};
class Client
{
public:
Client()
{
QString request = "***";
for (int i = 0; i < 5; ++i)
{
srand((unsigned)time(NULL));
int num = rand() % (4 - 1) + 1;
EType type = EType(num);
IWomen* women = new Women(type, request);
m_womens.push_back(women);
}
}
void request()
{
IHandler *father = new Father();
IHandler *husband = new Husband();
IHandler *son = new Son();
QList::ConstIterator iter = m_womens.begin();
while(iter != m_womens.end())
{
IWomen* women = *iter;
if (women->getType() == ENotMarry)
{
father->HandleMessage(women);
}
else if (women->getType() == EMarry)
{
husband->HandleMessage(women);
}
else if (women->getType() == ENothusband)
{
son->HandleMessage(women);
}
else{}
++iter;
}
}
private:
QList m_womens;
};
int main()
{
Client client;
client.request();
return 0;
}
我们使用一个枚举来表示女性的不同状态
ENotMarry :未婚 ,EMarry:已婚,丈夫健在,ENothusband:丈夫去世。从整个设计上分析,有处理权的人(如父亲、丈夫、儿子)才是设计的核心,他们是要处理这些请求的。
①职责界定不清晰。女儿提出的请示,应该在父亲类中作出决定,把原本应该是父亲类做的事情抛给了其他类进行处理。
②代码臃肿。在 Client 中写了 if...else 的条件判断,随着处理该类型的请示人员越多,判断就越多。
③耦合过重。要根据Women 的 type 来决定使用 IHandler 的哪个实现类来处理请求。如果 IHandler 的实现类继续扩展,需要修改 Client 类,与开闭原则违背了。
④异常情况欠考虑。如果妻子向父亲请求指示,父亲应该如何处理,在程序上没有体现出来,逻辑失败了。
女性提出一个请示,必然要获得一个答复,而且这个答案是唯一的,重新设计后,抽象这样一个结构,女性的请求先发送到父亲类,父亲类一看是自己要处理的,就作出回应,如果女儿已经出嫁就把请求转发给女婿。父亲、丈夫、儿子每个节点有两个选择:要么作出回应,要么把请求转发到后续环节。
顺序处理图:16-2
三个实现类 Father、Husband、Son 只要实现构造函数和父类中的抽象方法 response 就可以了,具体由谁处理女性提出的请求,都已经转移到了 Handler 抽象类中。
////////////////// ********** 2. 妇女“三从”改善设计,代码清单16-2:***************//
enum EType
{
ENotMarry = 1,
EMarry ,
ENothusband
};
class IWomen
{
public:
virtual int getType() = 0; //获得个人状况
virtual QString getRequest() = 0; //获得个人请示
};
class Women:public IWomen
{
public:
Women(EType type, QString request)
{
this->m_type = type;
this->m_request = request;
}
virtual int getType()
{
return this->m_type;
}
virtual QString getRequest()
{
return this->m_request;
}
private:
EType m_type;
QString m_request;
};
class Handler
{
public:
Handler(){}
Handler(EType type)
{
this->m_type = type;
}
void HandleMessage(IWomen *women)
{
if (women->getType() == this->m_type)
{
this->response(women);
}
else
{
if (this->m_nextHandler != nullptr)
{
this->m_nextHandler->HandleMessage(women);
}
else
{
qDebug() << "NO!";
}
}
}
void setNext(Handler *handler)
{
this->m_nextHandler = handler;
}
protected:
virtual void response(IWomen *women) = 0;
protected:
EType m_type;
Handler *m_nextHandler;
};
class Father:public Handler
{
public:
Father()
{
this->m_type = ENotMarry;
}
virtual void response(IWomen *women)
{
qDebug() << "request:" << women->getRequest();
qDebug() << "Father restore: ...";
}
};
class Husband:public Handler
{
public:
Husband()
{
this->m_type = EMarry;
}
virtual void response(IWomen *women)
{
qDebug() << "request: "<< women->getRequest();
qDebug() << "Husband restore: ...";
}
};
class Son:public Handler
{
public:
Son()
{
this->m_type = ENothusband;
}
virtual void response(IWomen *women)
{
qDebug() << "request: "<< women->getRequest();
qDebug() << "Son restore: ...";
}
};
class Client
{
public:
Client()
{
QString request = "***";
for (int i = 0; i < 5; ++i)
{
srand((unsigned)time(NULL));
int num = rand() % (4 - 1) + 1;
EType type = EType(num);
IWomen* women = new Women(type, request);
m_womens.push_back(women);
}
}
void request()
{
Handler *father = new Father();
Handler *husband = new Husband();
Handler *son = new Son();
father->setNext(husband);
husband->setNext(son);
QList::ConstIterator iter = m_womens.begin();
while(iter != m_womens.end())
{
IWomen* women = *iter;
if (women->getType() == ENotMarry)
{
father->HandleMessage(women);
}
else if (women->getType() == EMarry)
{
husband->HandleMessage(women);
}
else if (women->getType() == ENothusband)
{
son->HandleMessage(women);
}
else{}
++iter;
}
}
private:
QList m_womens;
};
int main()
{
Client client;
client.request();
return 0;
}
其实这里也用到模板方法模式,在模板方法中判断请求的类型和当前能够处理的类型,如果相同调用基本方法,作出反馈,如果不相等,则传递到下一个环节,由下一环节作出回应,如果已经达到环节尾部,则直接做不同意处理。基本方法 response 需要各个实现类实现,每个实现类只要实现两个职责:一是定义自己能够处理的等级级别;而是对请求作出回应。
将请求和处理分开。请求者可以不知道是谁处理的,处理者可以不用知道请求的全貌,两者解耦,提高系统的灵活性。
①性能问题。每个请求都是从链头遍历到链尾,特别是在链比较长的时候,性能是一个非常大的问题。
②调试不便。特别是链条比较长,环节比较多的时候,由于采用了类似递归的方式,调试时逻辑可能比较复杂。
链中节点数量需要控制,避免出现超长链的情况,一般做法是在 Handler 中设置一个最大的节点数量,在 setNext 方法中判断是否已经是超过其阈值,超过则不允许建立该链,避免无意识地破坏系统性能。
参考文献《秦小波. 设计模式之禅》(第2版) (华章原创精品) 机械工业出版社