如何让孩子爱上设计模式 ——9.组合模式(Composite Pattern)

标签: 设计模式初涉


描述性文字

组合模式,又称为 部分整体模式,把具有相似的一组对象
当做一个对象处理,用一种树状的结构来组合对象,再提供统一
的方法去访问相似的对象,以此忽略掉对象与对象容器间的差别。

举个简单例子,菜单和菜品,同样是以小猪的奶茶店为例子:

假设这两类需求如下:

菜单:菜单名,描述信息,添加,添加删除子菜单或菜品
递归打印出所有的子菜单与菜品!

菜品:菜名,描述信息,价格,打印信息

好的,先试试不用组合模式,要怎么写~


不使用组合模式写菜单

1.先把四个菜品都创建出来,一样的结构,名称,描述,价格,打印:

2.创建菜单类,名称,描述信息,可以增删菜品,子菜单,遍历打印:

3.客户端调用

4.打印结果

好的,没毛病,但是问题来了,如果增删菜品或者子菜单,原有代码
都要进行相应的修改,扩展性差,如果引入组合模式会又会如何?


使用组合模式写菜单

1.抽象出即可代表菜单又可代表菜品的类,这里我们只需要一个
add,get,getString三个抽象方法,让菜单和菜品去继承,菜品
只需完成getString方法重写,菜单需要重写add和get方法。

2.四个照葫芦画瓢的菜品类

3.菜单类

4.客户端调用

5.打印结果

使用了合并模式,如果此时我们要新增一个菜品,只需继承抽象构建类,
无需改动其他类,显得更加方便。


概念与总结


三个角色

上面也说了合并模式是用一种树状的结构来组合对象,三个名词
根节点枝结点叶子结点,类比上面那个菜单的图,
根节点是菜单,枝结点是饮料菜单和小吃菜单,
叶子结点是奶茶,果汁,手抓饼和鱼蛋!

  • Component抽象组件,为组合中的对象声明接口,让客户端
    可以通过这个接口来访问和管理整个对象结构,可以在里面为定义的
    功能提供缺省的实现,比如上面的AbstractMenu类。
  • Composite容器组件,继承抽象组件,实现抽象组件中与
    叶子组件相关的操作,比如上面的Menu类重写了get,set方法。
  • Leaf叶子组件,定义和实现叶子对象的行为,不再包含其它
    的子节点对象,比如上面的MilkTea,Juice,HandCake,FishBall。

UML类图


使用情景

  • 如果你想表示对象的部分-整体层次结构,可以选用组合模式,
    把整体和部分的操作统一起来,使得层次结构实现更简单,从外
    部来使用这个层次结构也简单;
  • 如果你希望统一的使用组合结构中的所有对象,可以选用组合
    模式,这正是组合模式提供的主要功能;

优缺点

优点

让客户端更加简单,客户端不需要再操心面对的是组合对象还是叶节点
对象,所以不需要写一大堆if语句来保证他们对正确的对象调用了正确
的方法。通常,他们只需要对整个结构调用一个方法并执行操作就可以了。

缺点

容易增加新的组件也会带来一些问题,比如很难限制组合中的组件类型。
这在需要检测组件类型的时候,使得我们不能依靠编译期的类型约束来
完成,必须在运行期间动态检测。


本节代码

https://github.com/coder-pig/DesignPatternsExample/tree/master/8.Composite%20Pattern


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1 场景问题# 1.1 商品类别树## 考虑这样一个实际的应用:管理商品类别树。 在实现跟商品有关的应用系统的时候...
    七寸知架构阅读 6,116评论 10 59
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 174,533评论 25 709
  • 场景分析 我们平时去餐厅吃饭,都会使用菜单来点餐,今天我们来实现一个超级菜单,这个一个菜单大集合,包括单一菜品和子...
    西木柚子阅读 781评论 0 3
  • 人活着的时候总有一瞬间会觉得自己已经死去 可是死去的人或许不会知道自己是否活着 生死并存模糊不清 人们说真正的死亡...
    杋南阅读 250评论 0 0
  • 无论主角还是配角我们都承担好自己的角色的责任 我文笔不好,写不出来那种辞藻华丽地文字,我只能去真实的描述我的生活以...
    愿时光伴我成长阅读 427评论 0 0