外观模式应该是用的很多的一种模式,特别是当一个系统很复杂时,系统提供给客户的是一个简单的对外接口,而把里面复杂的结构都封装了起来。客户只需使用这些简单接口就能使用这个系统,而不需要关注内部复杂的结构。DP一书的定义:为子系统中的一组接口提供一个一致的界面, 外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。举个编译器的例子,假设编译一个程序需要经过四个步骤:词法分析、语法分析、中间代码生成、机器码生成。学过编译都知道,每一步都很复杂。对于编译器这个系统,就可以使用外观模式。可以定义一个高层接口,比如名为Compiler的类,里面有一个名为Run的函数。客户只需调用这个函数就可以编译程序,至于Run函数内部的具体操作,客户无需知道。下面给出UML图,以编译器为实例。

  1. #include<iostream>
  2. using namespace std;
  3. class Scanner
  4. {
  5. public:
  6. void Scan() { cout<<"词法分析"<<endl; }
  7. };
  8. class Parser
  9. {
  10. public:
  11. void Parse() { cout<<"语法分析"<<endl; }
  12. };
  13. class GenMidCode
  14. {
  15. public:
  16. void GenCode() { cout<<"产生中间代码"<<endl; }
  17. };
  18. class GenMachineCode
  19. {
  20. public:
  21. void GenCode() { cout<<"产生机器码"<<endl;}
  22. };
  23. //高层接口
  24. class Compiler
  25. {
  26. public:
  27. void Run()
  28. {
  29. Scanner scanner;
  30. Parser parser;
  31. GenMidCode genMidCode;
  32. GenMachineCode genMacCode;
  33. scanner.Scan();
  34. parser.Parse();
  35. genMidCode.GenCode();
  36. genMacCode.GenCode();
  37. }
  38. };
  39.  
  40. int main()
  41. {
  42. Compiler cr;
  43. cr.Run();
  44. return ;
  45. }

外观模式

这就是外观模式,它有几个特点(摘自DP一书),(1)它对客户屏蔽子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便。(2)它实现了子系统与客户之间的松耦合关系,而子系统内部的功能组件往往是紧耦合的。(3)如果应用需要,它并不限制它们使用子系统类。

结合上面编译器这个例子,进一步说明。对于(1),编译器类对客户屏蔽了子系统组件,客户只需处理编译器的对象就可以方便的使用子系统。对于(2),子系统的变化,不会影响到客户的使用,体现了子系统与客户的松耦合关系。对于(3),如果客户希望使用词法分析器,只需定义词法分析的类对象即可,并不受到限制。

外观模式在构建大型系统时非常有用。接下来介绍另一种模式,称为组合模式。感觉有点像外观模式,刚才我们实现外观模式时,在Compiler这个类中包含了多个类的对象,就像把这些类组合在了一起。组合模式是不是这个意思,有点相似,其实不然。

DP书上给出的定义:将对象组合成树形结构以表示“部分-整体”的层次结构。组合使得用户对单个对象和组合对象的使用具有一致性。注意两个字“树形”。这种树形结构在现实生活中随处可见,比如一个集团公司,它有一个母公司,下设很多家子公司。不管是母公司还是子公司,都有各自直属的财务部、人力资源部、销售部等。对于母公司来说,不论是子公司,还是直属的财务部、人力资源部,都是它的部门。整个公司的部门拓扑图就是一个树形结构。

下面给出组合模式的UML图。从图中可以看到,FinanceDepartment、HRDepartment两个类作为叶结点,因此没有定义添加函数。而ConcreteCompany类可以作为中间结点,所以可以有添加函数。那么怎么添加呢?这个类中定义了一个链表,用来放添加的元素。

  1. #include<iostream>
  2. #include <list>
  3. using namespace std;
  4. class Company
  5. {
  6. public:
  7. Company(string name) { m_name = name; }
  8. virtual ~Company(){}
  9. virtual void Add(Company *pCom){}
  10. virtual void Show(int depth) {}
  11. protected:
  12. string m_name;
  13. };
  14. //具体公司
  15. class ConcreteCompany : public Company
  16. {
  17. public:
  18. ConcreteCompany(string name): Company(name) {}
  19. virtual ~ConcreteCompany() {}
  20. void Add(Company *pCom) { m_listCompany.push_back(pCom); } //位于树的中间,可以增加子树
  21. void Show(int depth)
  22. {
  23. for(int i = ;i < depth; i++)
  24. cout<<"-";
  25. cout<<m_name<<endl;
  26. list<Company *>::iterator iter=m_listCompany.begin();
  27. for(; iter != m_listCompany.end(); iter++) //显示下层结点
  28. (*iter)->Show(depth + );
  29. }
  30. private:
  31. list<Company *> m_listCompany;
  32. };
  33. //具体的部门,财务部
  34. class FinanceDepartment : public Company
  35. {
  36. public:
  37. FinanceDepartment(string name):Company(name){}
  38. virtual ~FinanceDepartment() {}
  39. virtual void Show(int depth) //只需显示,无限添加函数,因为已是叶结点
  40. {
  41. for(int i = ; i < depth; i++)
  42. cout<<"-";
  43. cout<<m_name<<endl;
  44. }
  45. };
  46. //具体的部门,人力资源部
  47. class HRDepartment :public Company
  48. {
  49. public:
  50. HRDepartment(string name):Company(name){}
  51. virtual ~HRDepartment() {}
  52. virtual void Show(int depth) //只需显示,无限添加函数,因为已是叶结点
  53. {
  54. for(int i = ; i < depth; i++)
  55. cout<<"-";
  56. cout<<m_name<<endl;
  57. }
  58. };
  59.  
  60. int main()
  61. {
  62. Company *root = new ConcreteCompany("总公司");
  63. Company *leaf1=new FinanceDepartment("财务部");
  64. Company *leaf2=new HRDepartment("人力资源部");
  65. root->Add(leaf1);
  66. root->Add(leaf2);
  67.  
  68. //分公司A
  69. Company *mid1 = new ConcreteCompany("分公司A");
  70. Company *leaf3=new FinanceDepartment("财务部");
  71. Company *leaf4=new HRDepartment("人力资源部");
  72. mid1->Add(leaf3);
  73. mid1->Add(leaf4);
  74. root->Add(mid1);
  75. //分公司B
  76. Company *mid2=new ConcreteCompany("分公司B");
  77. FinanceDepartment *leaf5=new FinanceDepartment("财务部");
  78. HRDepartment *leaf6=new HRDepartment("人力资源部");
  79. mid2->Add(leaf5);
  80. mid2->Add(leaf6);
  81. root->Add(mid2);
  82. root->Show();
  83.  
  84. delete leaf1; delete leaf2;
  85. delete leaf3; delete leaf4;
  86. delete leaf5; delete leaf6;
  87. delete mid1; delete mid2;
  88. delete root;
  89. return ;
  90. }

组合模式

C++外观模式和组合模式的更多相关文章

  1. 设计模式GOF23(结构型模式:代理模式,适配模式,桥接模式,组合模式,装饰模式,外观模式,享元模式)

    结构型模式: – 分类: • 适配器模式.代理模式.桥接模式.装饰模式.组合模式.外观模式.享元模式 – 核心作用:是从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题.   结构 ...

  2. Java计模模式之六 ----- 组合模式和过滤器模式

    前言 在上一篇中我们学习了结构型模式的外观模式和装饰器模式.本篇则来学习下组合模式和过滤器模式. 组合模式 简介 组合模式是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来 ...

  3. 迭代器模式和组合模式(head first设计模式——8)

    把迭代器模式和组合模式放在同一篇的原因是其联系比较紧密. 一.迭代器模式 1.1迭代器模式定义 迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而不是暴露其内部的表示. 这个模式提供了一种方法 ...

  4. 设计模式16---设计模式之组合模式(Composite)(行为型)

    1.场景模拟 使用软件模拟大树的根节点和树枝节点和叶子节点 抽象为两类,容器节点和叶子节点 2.不用模式的解决方案 package demo14.composite.example1; import ...

  5. 设计模式---数据结构模式之组合模式(Composite)

    前提:数据结构模式 常常有一些组建在内部具有特定的数据结构,如果让客户程序依赖这些特定的数据结构,将极大的破坏组件的复用.这时候,将这些数据结构封装在内部,在外部提供统一的接口,来实现与特定数据结构无 ...

  6. javascript设计模式----桥接模式、组合模式、装饰者模式、享元模式

    http://blog.csdn.net/painsonline/article/details/7215087    桥接模式:http://www.cnblogs.com/TomXu/archiv ...

  7. [19/04/26-星期五] GOF23_结构型模式(桥接模式、组合模式)

    一.桥接模式(bridge) 场景:商城系统中常见的商品分类,以电脑为例,首先想到使用多层继承结构. —— 台式机(联想台式机.戴尔台式机.神舟台式机) 电脑    ——笔记本(联想笔记本.戴尔笔记本 ...

  8. Java设计模式(8)——结构型模式之组合模式(Composite)

    一.概述 定义 将对象以树形结构组织起来,以达成“部分-整体” 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性. 简图 角色——对应上图中顶点为Component,左边为Leaf,右边为C ...

  9. GoF23种设计模式之结构型模式之组合模式

    一.概述 将对象组合成树型结构以表示“部分--整体”的层次关系.组合模式使得用户对单个对象和组合对象的使用具有一致性. 二.适用性 1.你想表示对象的部分--整体层次结构的时候. 2.你希望用户忽略组 ...

随机推荐

  1. Windows下TeX Live + Sublime Text 3 + Sumatra PDF配置

    本文写给我的师弟们,如何自己动手配置LaTeX环境(通过LeX Live + Sublime Text 3 + Sumatra PDF). 1.TeX Live 配置 首先从TeX Live 下载IS ...

  2. C指针乱谈(1)

    写了几年的C指针几乎没怎么用过,因为感觉没什么用.不过在听了一位老师讲课之后,我改变的我的想法. 在此稍做总结,希望能帮到一些和我有同样想法的人,希望看完这篇文章后能改变您的想法. 首先,说说概念,指 ...

  3. idea 开启 tomcat 访问日志记录

    all 为 设置为 查看所有类型的请求 (包括ajax)

  4. [LOJ#6066]. 「2017 山东一轮集训 Day3」第二题[二分+括号序列+hash]

    题意 题目链接 分析 首先二分,假设二分的答案为 \(mid\),然后考虑利用括号序列来表示树的形态. 点 \(u\) 的 \(k-\) 子树的括号序列表示实际上是刨去了 \(u\) 子树内若干个与 ...

  5. NetBeans 插件开发简介

    希望 NetBeans 为您提供更多功能吗? 您希望倾心投入到 NetBeans 的开发中,并希望它能激发您开发另一个应用程序的热情.您希望聆听音乐.浏览网页.查看邮件.存储喜欢的 URL,以及维护日 ...

  6. vuex实践之路——笔记本应用(一)

    首先使用vue-cli把环境搭建好. 介绍一下应用的界面. App.vue根组件,就是整个应用的最外层 Toolbar.vue:最左边红色的区域,包括三个按钮,添加.收藏.删除. NoteList.v ...

  7. 【原】Github+Hexo+NextT搭建个人博客【1】

    该系列博客列表请访问:http://www.cnblogs.com/penglei-it/category/934299.html 摘要 GitHub 是一个开源项目的托管网站,相信很多人都听过.在上 ...

  8. Unity3D Shader 学习笔记(一):初识Shader

    第一节:图形处理器简史 GPU发展简史 GPU英文全称Graphic Procssing Unit. T&L变换和光照流水线 可编程GPU GPU的优点和缺点 第二节:Unity Shader ...

  9. 0.1 Maven相关知识(项目开发基础)

    一.Maven 1.1Maven是什么 Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件. Maven这个单词来自于意第绪语(犹太语),意为知识的 ...

  10. java 软件开发面试宝典

    一. Java 基础部分........................................................................................ ...