《迭代器与组合模式》PPT课件
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
25
代码
Leaf节点,实现菜单项
26
代码
Composite节点,组合菜单
迭代器
27
代码
28
运行
29
总结
• 迭代器允许访问聚合的元素,而不需要暴露它的内部结构 • 迭代器将遍历集合的工作封装进一个对象中 • 当使用迭代器的时候,我们依赖聚合提供遍历 • 迭代器提供一个通用的接口,可以遍历聚合的项,当编码使
• 我们需要确定能够在每个菜单的各个项之间游 走,而且至少像用迭代器一样方便
• 我们能够弹性在菜单项之间游走,如:可以只 遍历甜点菜单,或者可以遍历餐厅整个菜单
22
定义组合模式
• 定义:允许将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客 户以一致的方式处理个别对象(叶子接点)及对象组合(中间节点)。
4
问题分析
合并前,两家餐厅的 菜单项存储格式不一样
5
问题分析
③合并后的新餐厅能够遍历菜单每一项,可以打印出所有素食菜单项
如果还有第三家餐厅 合并进来,需要三 个循环……
我们必须实现两个不同的循环,分别 处理这两个不同的菜单
6
解决问题
现在我们创建一个迭代器对象(Iterator),利用 它来封装”便历集合内的每个对象的过程”。 Iterator iterator=breakfastMenu.createIterator();
③Leaf节点:实现Component接口类的实例,不可以包含其它Composite 节点或Leaf节点的引用
23
UML类图
《interface》 Component
+add(Component):void +remove(Component) +getChild(int):Component +operation():void
Leaf
+operation():void
24
Composite
child:LinkedList
+add(Component):void +remove(Component) +getChild(int):Component +operation():void
利用组合设计菜单
抽象组件
有些方法适合菜单项,有些方法 适合于菜单; 面对这种情况,最好抛出运行时异常
15
举例
• 由于只有早餐和午餐,缺乏竞争力,将咖啡厅也合并进来,供应晚餐
我们使用很常见的存储结构Hashtable
我们不是取得整个Hashtable的迭代器,而是取值部分 的迭代器
16
合并餐厅代码
有什么问 题?
17
运行
18
问题
• 我们发现:在合并新餐厅代码中每次有新菜单加入,我们 必须加入新代码,在程序中调用三次printMenu( ).违背 “开放-关闭”原则
hasNext() next() remove()
8
用迭代器改写餐厅菜单-1
返回一个针对该集合的具体迭代器
9
用迭代器改写餐厅菜单-2
不创建自己的迭代器,而是调用 菜单项ArrayList的iterator()方法,获得具体迭代器。
让这两家餐厅菜单类都实现Menu接口
10
代码
每个餐厅菜单类都必须负责 建立适当的具体迭代器。
第七章
迭代器与组合模式
回顾
• 模板方法定义了算法的步骤,把这些步骤的实现延迟到子 类
• 模板方法模式为我们提供一种代码复用的重要技巧 • 模板方法的抽象类可以定义具体方法、抽象方法和Hook • Hook是一种方法,它在抽象类中不做事,或者只做默认的
事情,子类可以选择要不要去覆盖它。
2
目标
• 迭代器允许访问聚合的元素,而不需要暴露它的内部结构 • 迭代器将遍历集合的工作封装进一个对象中 • 当使用迭代器的时候,我们依赖聚合提供遍历 • 迭代器提供一个通用的接口,可以遍历聚合的项,当编码使
我们利用ArrayList将每个餐厅菜单存储进来
利用迭代器遍历菜单
19
运行
20
问题
• 我们希望午餐后提供一份甜点”子菜单”(菜单中的菜单)
所有菜单
ArrayList,持有每家餐厅的菜单
BreakfastMenu DinerMenu
1
2
CafeMenu
3
wk.baidu.com晚餐菜单
Hashtable
早餐菜单
MenuItem MenuItem
• 组合模式关键在于无论是个体对象还是组合对象都实现了相 同的接口或都是同一个抽象类的子类。
• 模式结构:三种角色
①抽象组件(Component):是一个接口(抽象类),该接口定义了个体对象和组合 对象需要实现的关于操作其子节点的方法或用于操作其自身的方法。
②Composite节点:实现Component接口类的实例,同时可以含有其它Composite 节点或Leaf节点的引用
11
运行
12
UML类图
13
定义迭代器模式
• 定义:提供一种方法顺序访问一个聚合对象中的各个元素, 而又不暴露其内部的表示。
• 注意:
①迭代器模式让我们能游走于聚合内的每一个元素,而又不暴露其内部的表 示;
②把游走的任务放在迭代器上,而不是聚合上。这样简化聚合的接口和实 现,也让责任各得其所。
14
用聚合的项时,就可以使用多态机制 • 组合模式提供一个结构,可同时包含个别对象和组合对象 • 使用组合结构,我们能把相同操作应用在组合和个别对象
上。
30
感谢下 载
while(iterator.hasNext()){ MenuItem menuItem=(MenuItem)iterator.next(); }
Iterator iterator=DinerMenu.createIterator(); while(iterator.hasNext()){
MenuItem menuItem=(MenuItem)iterator.next(); }
模式结构
• 包括四种角色
①集合(Aggregate):一个接口,定义具体集合需实现的操作
②具体集合(ConcreteAggregate):具体集合是实现集合接口的类的实例,具体 集合按照一定结构存储对象,具体集合应当有一个方法,该方法返回一个针对 该集合的具体迭代器 ③迭代器(Iterator):一个接口,规定遍历具体集合的方法 ④具体迭代器(ConcreteIterator)实现迭代器接口的类的实例
遍历集合的每个对象过程 封装起来! 不用暴露出对象的存储形式 看不到ArrayList、数组
7
迭代器模式
• 它依赖于一个迭代器接口: 一旦我们有了这个接口,就 可以为各种对象集合实现迭代器
《interface》 Iterator
hasNext() next() remove
DinerMenuIterator
用聚合的项时,就可以使用多态机制 • 组合模式提供一个结构,可同时包含个别对象和组合对象 • 使用组合结构,我们能把相同操作应用在组合和个别对象
上。
3
举例
• 两家餐厅(一家做早餐的,另一家做午餐的),由于市场竞争, 餐厅进行合并,我们来分析会出现什么问题?
①每家餐厅都有菜单项: ②每家餐厅菜单项存储方式不同
ArrayList
21
MenuItem
甜 MenuItem 点 菜 单
MenuItem
午餐菜单
MenuItem
MenuItem MenuItem
Array
MenuItem KEY
MenuItem KEY
午餐菜单持有一份子菜单,但是不能直接把它赋给菜单项数 组,因为类型不同。
解决问题
• 我们需要某种树形结构,可以容纳菜单、子菜 单和菜单项
代码
Leaf节点,实现菜单项
26
代码
Composite节点,组合菜单
迭代器
27
代码
28
运行
29
总结
• 迭代器允许访问聚合的元素,而不需要暴露它的内部结构 • 迭代器将遍历集合的工作封装进一个对象中 • 当使用迭代器的时候,我们依赖聚合提供遍历 • 迭代器提供一个通用的接口,可以遍历聚合的项,当编码使
• 我们需要确定能够在每个菜单的各个项之间游 走,而且至少像用迭代器一样方便
• 我们能够弹性在菜单项之间游走,如:可以只 遍历甜点菜单,或者可以遍历餐厅整个菜单
22
定义组合模式
• 定义:允许将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客 户以一致的方式处理个别对象(叶子接点)及对象组合(中间节点)。
4
问题分析
合并前,两家餐厅的 菜单项存储格式不一样
5
问题分析
③合并后的新餐厅能够遍历菜单每一项,可以打印出所有素食菜单项
如果还有第三家餐厅 合并进来,需要三 个循环……
我们必须实现两个不同的循环,分别 处理这两个不同的菜单
6
解决问题
现在我们创建一个迭代器对象(Iterator),利用 它来封装”便历集合内的每个对象的过程”。 Iterator iterator=breakfastMenu.createIterator();
③Leaf节点:实现Component接口类的实例,不可以包含其它Composite 节点或Leaf节点的引用
23
UML类图
《interface》 Component
+add(Component):void +remove(Component) +getChild(int):Component +operation():void
Leaf
+operation():void
24
Composite
child:LinkedList
+add(Component):void +remove(Component) +getChild(int):Component +operation():void
利用组合设计菜单
抽象组件
有些方法适合菜单项,有些方法 适合于菜单; 面对这种情况,最好抛出运行时异常
15
举例
• 由于只有早餐和午餐,缺乏竞争力,将咖啡厅也合并进来,供应晚餐
我们使用很常见的存储结构Hashtable
我们不是取得整个Hashtable的迭代器,而是取值部分 的迭代器
16
合并餐厅代码
有什么问 题?
17
运行
18
问题
• 我们发现:在合并新餐厅代码中每次有新菜单加入,我们 必须加入新代码,在程序中调用三次printMenu( ).违背 “开放-关闭”原则
hasNext() next() remove()
8
用迭代器改写餐厅菜单-1
返回一个针对该集合的具体迭代器
9
用迭代器改写餐厅菜单-2
不创建自己的迭代器,而是调用 菜单项ArrayList的iterator()方法,获得具体迭代器。
让这两家餐厅菜单类都实现Menu接口
10
代码
每个餐厅菜单类都必须负责 建立适当的具体迭代器。
第七章
迭代器与组合模式
回顾
• 模板方法定义了算法的步骤,把这些步骤的实现延迟到子 类
• 模板方法模式为我们提供一种代码复用的重要技巧 • 模板方法的抽象类可以定义具体方法、抽象方法和Hook • Hook是一种方法,它在抽象类中不做事,或者只做默认的
事情,子类可以选择要不要去覆盖它。
2
目标
• 迭代器允许访问聚合的元素,而不需要暴露它的内部结构 • 迭代器将遍历集合的工作封装进一个对象中 • 当使用迭代器的时候,我们依赖聚合提供遍历 • 迭代器提供一个通用的接口,可以遍历聚合的项,当编码使
我们利用ArrayList将每个餐厅菜单存储进来
利用迭代器遍历菜单
19
运行
20
问题
• 我们希望午餐后提供一份甜点”子菜单”(菜单中的菜单)
所有菜单
ArrayList,持有每家餐厅的菜单
BreakfastMenu DinerMenu
1
2
CafeMenu
3
wk.baidu.com晚餐菜单
Hashtable
早餐菜单
MenuItem MenuItem
• 组合模式关键在于无论是个体对象还是组合对象都实现了相 同的接口或都是同一个抽象类的子类。
• 模式结构:三种角色
①抽象组件(Component):是一个接口(抽象类),该接口定义了个体对象和组合 对象需要实现的关于操作其子节点的方法或用于操作其自身的方法。
②Composite节点:实现Component接口类的实例,同时可以含有其它Composite 节点或Leaf节点的引用
11
运行
12
UML类图
13
定义迭代器模式
• 定义:提供一种方法顺序访问一个聚合对象中的各个元素, 而又不暴露其内部的表示。
• 注意:
①迭代器模式让我们能游走于聚合内的每一个元素,而又不暴露其内部的表 示;
②把游走的任务放在迭代器上,而不是聚合上。这样简化聚合的接口和实 现,也让责任各得其所。
14
用聚合的项时,就可以使用多态机制 • 组合模式提供一个结构,可同时包含个别对象和组合对象 • 使用组合结构,我们能把相同操作应用在组合和个别对象
上。
30
感谢下 载
while(iterator.hasNext()){ MenuItem menuItem=(MenuItem)iterator.next(); }
Iterator iterator=DinerMenu.createIterator(); while(iterator.hasNext()){
MenuItem menuItem=(MenuItem)iterator.next(); }
模式结构
• 包括四种角色
①集合(Aggregate):一个接口,定义具体集合需实现的操作
②具体集合(ConcreteAggregate):具体集合是实现集合接口的类的实例,具体 集合按照一定结构存储对象,具体集合应当有一个方法,该方法返回一个针对 该集合的具体迭代器 ③迭代器(Iterator):一个接口,规定遍历具体集合的方法 ④具体迭代器(ConcreteIterator)实现迭代器接口的类的实例
遍历集合的每个对象过程 封装起来! 不用暴露出对象的存储形式 看不到ArrayList、数组
7
迭代器模式
• 它依赖于一个迭代器接口: 一旦我们有了这个接口,就 可以为各种对象集合实现迭代器
《interface》 Iterator
hasNext() next() remove
DinerMenuIterator
用聚合的项时,就可以使用多态机制 • 组合模式提供一个结构,可同时包含个别对象和组合对象 • 使用组合结构,我们能把相同操作应用在组合和个别对象
上。
3
举例
• 两家餐厅(一家做早餐的,另一家做午餐的),由于市场竞争, 餐厅进行合并,我们来分析会出现什么问题?
①每家餐厅都有菜单项: ②每家餐厅菜单项存储方式不同
ArrayList
21
MenuItem
甜 MenuItem 点 菜 单
MenuItem
午餐菜单
MenuItem
MenuItem MenuItem
Array
MenuItem KEY
MenuItem KEY
午餐菜单持有一份子菜单,但是不能直接把它赋给菜单项数 组,因为类型不同。
解决问题
• 我们需要某种树形结构,可以容纳菜单、子菜 单和菜单项