C++设计模式 之 “数据结构” 模式:Composite、Iterator、Chain of Resposibility
"数据结构"模式
常常有一些组件在内部具有特定的数据结构,如果让客户程序依赖这些特定的数据结构,将极大地破坏组件的复用。这时候,将这些特定数据结构封装在内部,在外部提供统一的接口,来实现与特定数据结构无关的访问,是一种行之有效的解决方案。
典型模式
#Composite
#Iterator
#Chain of Resposibility
part 1 Composite 模式
动机
#软件在某些情况下,客户代码过多地依赖于对象容器复杂的内部实现结构,对象容器内部实现结构(而非抽象接口)的变化将引起客户代码的频繁变化,带来了代码的维护性、拓展性等弊端。
#如何将“客户代码与复杂的对象容器结构”解耦?让对象容器自己来实现自身的复杂结构,从而使得客户代码就像处理简单对象一样来处理复杂的对象容器?
模式定义
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性(稳定)。——《设计模式》GoF
结构
结构 from 《大话设计模式》
代码 from 《大话设计模式》
1 #include <iostream> 2 #include <string> 3 #include <set> 4 5 using namespace std; 6 7 struct Company; 8 9 using depth = unsigned; 10 using container = set<Company*>; 11 12 struct Company { 13 virtual void display(depth d) = 0; 14 virtual void lineDuty() = 0; 15 }; 16 17 //brunch nood 18 struct ConcreteCompany : public Company { 19 container childrens; 20 string _name; 21 22 ConcreteCompany(string name) : _name(name) {}; 23 24 virtual void display(depth d) override { 25 for (depth i = 0; i < d; i++) 26 cout << "-"; 27 28 cout << _name <<endl; 29 30 for(auto e : this -> childrens) 31 e->display(d + 1); 32 } 33 34 virtual void lineDuty() override { 35 for (auto e : childrens) 36 e->lineDuty(); 37 } 38 39 void add(Company* c) { 40 this -> childrens.insert(c); 41 } 42 43 void remove(Company* c) { 44 this -> childrens.erase(c); 45 } 46 }; 47 48 //leaf nood 49 struct FinanceDepartment : public Company { 50 string _name; 51 52 FinanceDepartment(string name) : _name(name) {}; 53 54 virtual void display(depth d) override { 55 for (depth i = 0; i < d; i++) 56 cout << "-"; 57 58 cout << _name << endl; 59 } 60 61 virtual void lineDuty() override { 62 cout << _name << "财务部 公司收支管理" << endl; 63 } 64 }; 65 66 //leaf nood 67 struct HRDepartment : public Company { 68 string _name; 69 70 HRDepartment(string name) : _name(name) {}; 71 72 virtual void display(depth d) override { 73 for (depth i = 0; i < d; i++) 74 cout << "-"; 75 76 cout << _name << endl; 77 } 78 79 virtual void lineDuty() override { 80 cout << _name << "人力资源部 员工招聘培训管理" << endl; 81 } 82 }; 83 84 int main() { 85 ConcreteCompany *root = new ConcreteCompany("北京总公司"); 86 root->add(new HRDepartment("总公司人力资源部")); 87 root->add(new FinanceDepartment("总公司财务部")); 88 89 ConcreteCompany *comp = new ConcreteCompany("上海华东分公司"); 90 comp->add(new HRDepartment("华东分公司人力资源部")); 91 comp->add(new FinanceDepartment("华东分公司财务部")); 92 root->add(comp); 93 94 ConcreteCompany *comp1 = new ConcreteCompany("南京办事处"); 95 comp1->add(new HRDepartment("南京办事处人力资源部")); 96 comp1->add(new FinanceDepartment("南京办事处财务部")); 97 comp->add(comp1); 98 99 ConcreteCompany *comp2 = new ConcreteCompany("杭州办事处"); 100 comp2->add(new HRDepartment("杭州办事处人力资源部")); 101 comp2->add(new FinanceDepartment("杭州办事处财务部")); 102 comp->add(comp2); 103 104 cout << "结构图" << endl; 105 root->display(1); 106 107 cout << "职责" << endl; 108 root->lineDuty(); 109 110 return 0; 111 }
要点总结
#Composite模式采用树形结构来实现普遍存在的对象容器,从而将“一对多”的关系转化为“一对一”的关系,使得客户代码可以一致地(复用)处理对象和对象容器,无需关心处理的是单个的对象,还是组合的对象容器。
#将“客户代码与复杂的对象容器结构”解耦的是Composite的核心思想,解耦之后,客户代码将与纯粹的抽象接口——而非对象容器的内部实现结构——发生依赖,从而更能“应对变化”。
#Composite模式在具体实现中,可以让父对象中的字对象反向追溯;如果父对象有频繁的遍历需求,可以使用缓存技巧来改善效率。
智慧在街市上呼喊,在宽阔处发声。