软件工程|组合模式与职责链模式编程实现
组合模式 简介
将对象组合成树形结构以表示“部分-整体”的层次结构。
组合模式使得用户对单个对象和组合对象的使用具有一致性。
动机
总部、分部和办事处是成树状结构,也就是有组织结构的,不可以简单的平行管理。
希望总公司的组织结构,比如人力资源部、财务部的管理功能可以复用于分公司。这其实是整体与部分可以被一致对待的问题。
适用性
想表示对象的“部分-整体”层次结构。
希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
结构
文章图片
参与者
Component
为组合中的对象声明接口。
在适当的情况下,实现所有类共有接口的缺省行为。
声明一个接口用于访问和管理Component的子组件。
在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。(可选)
Leaf
在组合中表示叶节点对象,叶节点没有子节点。
在组合中定义叶节点对象的行为。
Composite
定义有子部件的那些部件的行为。
存储子部件。
在Component接口中实现与子部件有关的操作。
Client
通过Component接口操纵组合部件的对象。
协作
用户使用Component类接口与组合结构中的对象进行交互。
如果接收者是一个叶节点,则直接处理请求。
如果接收者是一个Composite,它通常将请求发送给它的子部件,在转发请求之前与/或之后可能执行一些辅助操作。
效果
定义了包含基本对象和组合对象的类层次结构。
简化客户代码。
使得更容易添加新类型的组件。
职责链模式 简介
为解除请求的发送者和接收者之间的耦合,而使多个对象都有机会处理这个请求。
将这些对象连成一条链,并沿着这条链传递该请求,指导有一个对象处理它为止。
动机
考虑公司中的请假申请。
公司中管理人员按等级从低到高分别有:经理、总监、总经理。
请假需要根据天数长短,向不同等级的管理人员申请,例如少于2天直接向经理申请即可,少于一周必须要总监批准,更长时间则需要总经理批准。
适用性
有多个对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
可处理一个请求的对象集合应被动态指定。
结构
【软件工程|组合模式与职责链模式编程实现】
文章图片
参与者
Handler
定义一个处理请求的接口。
实现后继链。
ConcreteHandler
处理它所负责的请求。
可访问它的后继者。
如果可处理该请求,就处理之;否则将该请求转发给它的后继者。
Client
向链上的ConcreteHandler对象提交请求。
效果
降低耦合度。
增强了给对象指派职责的灵活性。
不保证被接受。
实例 根据下图,利用组合模式构建该公司的结构。
文章图片
即总公司下设上海华东分公司,华东分公司下设南京办事处和杭州办事处。其中,各级分公司均设有人力资源部和财务部。
利用组合模式构建好该结构后,利用职责链模式处理各地员工加薪请求。
例如,一南京员工提出加薪请求,如果加薪不超过1000元,南京办事处即可批准;如果超过1000元,则上报华东分公司,如果2000元以内,则批准;超过则上报北京总公司,如果不超过3000元,则总公司批准,否则拒绝。
UML
文章图片
组合模式Component是对象声明接口,对应于职责链模式的Handler,两个模式的代码可以合并。
另外通过增加low, bound两个变量来控制if语句数量,减少类的数目。因此职责链中的多个ConcreteHandler对应于一个具体的ConcreteCompany。
代码
#include
#include
#include
using namespace std;
class Component{
public:
Component(string name){
this->name = name;
}
virtual void Add(Component* c) = 0;
virtual void Remove(Component* c) = 0;
virtual void Display(int depth) = 0;
void SetSuccessor(Component* s){
this->successor = s;
}
void SetBound(int low, int high){
this->low = low;
this->high = high;
}
virtual void HandleReauest(int request) = 0;
protected:
string name;
int low, high;
Component* successor;
};
class Subcom : public Component{
public:
Subcom(string name) : Component(name){}
void Add(Component* c){
cout<<"Cannot add to a leaf";
}
void Remove(Component* c){
cout<<"Cannot remove from a leaf";
}
void Display(int depth){
for(int i = 0;
i <= depth;
i++)
cout<<"--";
cout< children;
public:
ConcreteCompany(string name): Component(name){}
void Add(Component *c){
children.push_back(c);
}
void Remove(Component *c){
children.remove(c);
}
void Display(int depth){
for(int i = 0;
i <= depth;
i++)
cout<<"--";
cout<Display(depth + 1);
}
}
void HandleReauest(int request){
if(request >= low && request <= high){
cout<name<<"处理请求: "<name<<"处理失败"<HandleReauest(request);
}else{
cout<name<<"加薪拒绝"<Add(new Subcom("人力资源部"));
root->Add(new Subcom("财务部"));
root->SetBound(2000, 3000);
Component *huadong = new ConcreteCompany("上海华东分公司");
huadong->Add(new Subcom("人力资源部"));
huadong->Add(new Subcom("财务部"));
huadong->SetBound(1000, 2000);
Component *nanjing = new ConcreteCompany("南京办事处");
nanjing->Add(new Subcom("人力资源部"));
nanjing->Add(new Subcom("财务部"));
nanjing->SetBound(0, 1000);
Component *hanzhou = new ConcreteCompany("杭州办事处");
hanzhou->Add(new Subcom("人力资源部"));
hanzhou->Add(new Subcom("财务部"));
hanzhou->SetBound(0, 1000);
nanjing->SetSuccessor(huadong);
hanzhou->SetSuccessor(huadong);
huadong->SetSuccessor(root);
root->SetSuccessor(NULL);
huadong->Add(nanjing);
huadong->Add(hanzhou);
root->Add(huadong);
root->Display(1);
cout<<"*********************"<HandleReauest(100);
cout<<"*********************"<HandleReauest(1500);
cout<<"*********************"<HandleReauest(2100);
cout<<"*********************"<HandleReauest(3100);
return 0;
}
//
结果
文章图片
总结
①本次需要将职责链模式与组合模式合并,其中组合模式Component是对象声明接口,对应于职责链模式的Handler。
②组合模式中的节点需要放到当前父节点的list中,对于容器list,需要掌握对应的STL语句。
③对于职责链模式,为了减少类的数量和耦合需要设置low和high两个上下界。类虽然少了,但是对象没有减少,这些对象形成一条链,并沿着这条链传递该请求,直到有一个对象处理了它为止。通过当前对象的name来指示客户端选择。
更多内容访问 omegaxyz.com
网站所有代码采用Apache 2.0授权
网站文章采用知识共享许可协议BY-NC-SA4.0授权
? 2019 ? OmegaXYZ-版权所有 转载请注明出处
推荐阅读
- 21天|21天|羊多多组合《书都不会读,你还想成功》
- --木木--|--木木-- 第二课作业#翼丰会(每日一淘6+1实战裂变被动引流# 6+1模式)
- 设计模式-代理模式-Proxy
- 2018-08-29|2018-08-29 - 草稿 - 草稿
- 【译】Rails|【译】Rails 5.0正式发布(Action Cable,API模式等)
- java静态代理模式
- VueX(Vuex|VueX(Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式)
- Kotlin基础(10)-代理模式在kotlin中的使用
- 长谈的确是这个时代需要的一种模式
- 《读_Head_First_有感》_“命令模式”