调侃《Head First设计模式》之迭代器和组合模式(一)

      现在餐厅来了两个新的厨师A和B,他们各自有各自实现菜单的方式。A的方式是将菜单项放在一个ArrayList当中的菜单,而B则是将菜单项放在数组当中的菜单。一个菜单项的类如下:

     调侃《Head First设计模式》之迭代器和组合模式(一)_第1张图片

       餐厅的侍女的任务是对顾客需求打印定制的菜单,甚至告诉人们哪一个菜单项是素食。招代规格如下图:

      调侃《Head First设计模式》之迭代器和组合模式(一)_第2张图片

       两个厨师接收不同的菜单会导致什么问题呢?如果侍女要打印出所有菜单项,对于A厨师来说需要循环遍历集合中的元素,对于B来说,则需要循环遍历数组中的元素,如下图:

       调侃《Head First设计模式》之迭代器和组合模式(一)_第3张图片

      如果增加新的菜单实现,则又要加上一个循环遍历,这样侍女的代码将难以维护和扩展。

    看过之前的文章,很容易想到要让侍女代码容易维护扩展,就要让代码摆脱遍历的具体实现。我们发现其实两个循环遍历有很多相似的地方,那何不将遍历封装起来,这样让侍女去调用封装起来的遍历不就可以了?

   

    现在我们创建一个叫做迭代器的东西,用它封装遍历实现,一个菜单只要获得它的迭代器就可以遍历菜单的所有菜单项。类似如下代码:

    调侃《Head First设计模式》之迭代器和组合模式(一)_第4张图片

     使用上面的代码,不管具体的菜单实现是什么,都可遍历所有元菜单项。

      从代码入手,根据以前的经验,所有迭代器有一个统一的接口:

    调侃《Head First设计模式》之迭代器和组合模式(一)_第5张图片

      创建一个具体的迭代器实现该接口,比如数组方式实现的菜单:

      调侃《Head First设计模式》之迭代器和组合模式(一)_第6张图片

      这样我们的菜单实现可以如下所示:

     调侃《Head First设计模式》之迭代器和组合模式(一)_第7张图片

    具体的菜单返回具体的迭代器,客户只需要一个迭代器就可以遍历所有菜单。ArrayList实现的PancakeHouseMenu代码也是极为相似,这里留给读者思考。

    再看一次新的侍女代码:

    调侃《Head First设计模式》之迭代器和组合模式(一)_第8张图片

     看,不同的菜单在侍女这里都可以用统一的方法实现遍历啦!实现了侍女和具体的菜单实现的解耦,侍女不需要知道菜单如何实现(数组或者集合等),她要的只是一个迭代器,就可以遍历所有菜单项。整个设计的类图:

     调侃《Head First设计模式》之迭代器和组合模式(一)_第9张图片

     具体的菜单创建具体的迭代器,侍女要的只是一个实现Iterator接口的类去遍历相应的菜单。

    以上是告诉你们迭代器的实现原理,其实java已经为我们提供了Iterator接口:

    调侃《Head First设计模式》之迭代器和组合模式(一)_第10张图片

    而且ArrayList本身已经设计好具体的迭代器了,只需要调用一个ArrayList集合的iterator方法就行。所以用集合实现的菜单的创建迭代器方法如下图:

   

    但是数组既不没有自己的迭代器了,所以数组还需要你去实现具体的迭代器:

    调侃《Head First设计模式》之迭代器和组合模式(一)_第11张图片

     

     这时候我们的侍女还是和具体的迭代器捆绑的,所以要使用共同的Menu接口来解耦。

    

    所以侍女的代码可以修改为:

    调侃《Head First设计模式》之迭代器和组合模式(一)_第12张图片

      修改后的类图:

      调侃《Head First设计模式》之迭代器和组合模式(一)_第13张图片

      这样侍女关心的只是两个接口,减少了对类的依赖,提高了可扩展性。

      我们看下官方对迭代器模式的定义:

     迭代器模式提供了一个方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的实现。把遍历元素的任务放在了迭代器而不是聚合对象,这样简化了聚合对象的接口和实现,也责任各得其所。

      典型的类图如下

      调侃《Head First设计模式》之迭代器和组合模式(一)_第14张图片

      说到责任各得其所,就不得不提一个设计原则:

      单一责任设计原则:一个类应该只有一个引起变化的原因。

      它告诉我们一个责任只能指派给一个类。因为与一个责任意味着一个潜在的改变区域,如果一个类的责任越多,则维护起来难度必定越大。当一个类被设计成只支持一组相关的功能时,我们说它是高内聚的。相对来说更易于维护。

       这篇文章先谈迭代器模式,下篇再继续以本故事来谈组合模式。

     

你可能感兴趣的:(java,设计模式)