组合模式引导篇及组合模式原理
在上一个《迭代器模式》中,我们讲到了阿里收购网易考拉后,店铺合并的问题使用到了迭代器模式。现在又有了新需求。我们先来看看新需求:
先说明:组合模式并非是把之前学过的设计模式组合在一起的一种模式哈。别理解错了。
来源:凯哥Java(kaigejava)
在原有菜单的基础上,新增餐后甜点功能,如在中餐厅(DinerMenu)中添加餐后甜点。
我们先来回顾下上一个模式下的类图,如下图:
从上图中,我们可以知道,服务员手里拿的菜单遥控器,只是三个iterator 迭代器接口对象。
方案一:也是正常的,最容易想到的方案。
在DinerMenu菜单后面再追加一个子项,用来表示甜点的菜单。如果,我们这样写了。其实最后,还是使用的迭代器模式的。本篇,我们讲解的是组合模式。所以,咱要玩点高大上的。咱使用组合模式来实现这个需求。
我们还可以这么想,将甜点设计成一个数据结构,然后将这个数据结构,放到中餐厅菜单的其中一个菜单下,让甜点菜单成为其子菜单。类图如下:
当我们点击dinnerMenu的第三个item的是,会弹出submenu,这样形式。
如果要实现,上面形式的数据结构,那么我们原有系统会遇到的问题:
一:数据结构怎么设计?怎么遍历获取每一个?
再上一个模式中,我们知道,无论是List<Item>(cakeHouseMenu)、数组结构(DinerMenu)还是hashTable结构的(cafeMenu)每一个菜单都是一个item对象。这样好遍历,但是现在的是有些item下面带有子菜单,这个怎么遍历出来?有的是item菜单项,有的是带有子菜单,因为数据类型不同的这是个问题。
因为涉及到了子菜单,也就有了父子关系的。再我们数据结构中,存在父子关系的,最先能想到的就是树这种结构了。所以,我们可以抽象的画出类图:
我们使用树形结构,节点是菜单或子菜单,叶子是菜单项,需要能够在各个菜单项之间游走,遍历。要能够有弹性的在菜单项之间游走。
从上图中,我们可以看出,在抽出一个超类,让叶子和含有叶子的节点都继承或实现这个超类。把原来存放item的都替换成抽出的超类,这样,整个体系中的数据类型都是同一个了。具体的,比如数组、list或者hashTable存放超类的子类。如,只放item的,我们就只放菜单项,还有甜点的,我们就放子菜单的。这样存储就统一了。
其实,组合模式的原理就是这样的。
凯哥个人博客:www.kaigejava.com
什么是组合模式:
组合模式又可以叫做部分-整体模式。是用于把一组类似的对象当作一个单一的对象。组合模式依据的是树形结构来组合对象,用来表示“部分或者是整体”的层次。
理解:
用于把一组类似的对象当作一个单一的对象什么意思呢?如我们的单个菜单项和带有子菜单的菜单项,这两个其实是一组类似的对象。我们再提供给服务员的时候,不管是单个菜单项还是带有子菜单的菜单项,对于服务员来说都是一个单一的对象。这下理解了吧。
用来表示部分以及整体层次怎么理解?请看下图:
其中部分是超类的子类,整体也是超类的这类,所以,我们在处理的时候,无论是子类还是整体都看作是单一的超类。
所以,我们可以得到组合模式其实需要解决的问题是:能让客户以一致的方法来处理个别对象以及对象组合的。简单理解就是:组合模式解决的问题是我们可以忽略对象组合与个体对象之间的差别的。
我们来看看,在组合模式下,新需求的类图:
从类图中,我们可以看到,cakeHouseMenu继承于MenuComponent对象;cakeHouseMenu下面的item也是继承于MenuComponent对象。
本篇文章花了大量口舌来讲解组合模式原理,希望大家能够更好的理解原理。在下一篇文章中,我们将使用代码来实现。