Java设计模式之迭代器模式和组合模式

简介:
迭代器模式
迭代器模式定义为,提供一种方法顺序访问聚合对象中的各个元素,又不暴露其内部的表示方法。
迭代器模式允许访问聚合中的各个元素,为客户提供了统一的方法去访问各个集合,屏蔽了具体集合的类型,无论是List,Map,Set,散列表,数组等集合,在客户端表现的都是一种方法来获取该集合中的元素。
通常迭代器将遍历聚合的工作封装进一个对象中,在我们使用迭代器的时候,我们依赖聚合提供遍历,通常聚合都会返回一个迭代器。这样就可以让集合只专注于元素的操作,而将对于元素游走的遍历工作放在迭代器上执行,这样就可以简化聚合的接口和实现。如果你有一个统一的方法来访问聚合中的每一个对象,则就可以利用多态的代码和这些聚合搭配。
迭代器类图如下
210929584.jpg
Aggregate:集合接口,提供了一个方法来给客户端来返回一个对于聚合元素访问遍历的迭代器
ConcreteAggregate:具体聚合持有了一个对象的集合,每一个具体聚合都要负责实例化与之对应的具体迭代器,此迭代器能够遍历对象集合。
Iterator:这是所有迭代器都要实现的接口,一般可以直接实现Java系统自带的Iterator。
ConcreteIterator:对于特定聚合对象进行遍历的算法。它主要负责遍历对象,以及判断对象。
注:在常用的各种集合对象中,list,Set均可以直接调用它们的方法 List.iterator();和Set.iterator();
一般对于如果是数组类型的,则就需要专门为数组做一个迭代器来转换它的遍历方式
对于Map集合的,由于Map集合是键值对的,所以要想取得它的值,
Map.values.iterator();//首先返回值的对象所有集合,然后再生成迭代器
一般迭代器是向前移动的,但是也可以实现向后移动,有一个ListIterator,这个可以实现向后移动元素的访问。迭代器遍历的结果并不是表示元素的大小次序的。在利用迭代器中,当一个方法的参数是一个迭代器的时候,其实就是使用了多态,我们此时针对接口编程而不是具体类编程,从而可以在不同的集合中遍历。
当然如果不想创建迭代器,可以直接利用foreach
代码示例:
有三个聚合类,一个用ArrayList存储对象,一个用数组存储对象,一个利用HashMap。由于三个集合访问遍历集合中的元素不同,但是为了给客户端提供一个统一的访问方法,此时就可以利用迭代器模式,为每一个集合创建一个对象的迭代器,再在聚合类中实例化该迭代器返回给客户端,这样客户端就只管遍历,而不用关心具体的集合类型了。
集合接口:存放元素的集合,并且为客户端返回一个集合的迭代器
package com.whut.iterator;
import java.util.Iterator;

public  interface Menu {
public Iterator createIterator();
}
利用数组存储对象的具体集合
package com.whut.iterator;

import java.util.Iterator;

public class DinerMenu  implements Menu{

private static final int MAX_ITEMS=6;
private int numberOfItems=0;
private MenuItem[] menuItems;

public DinerMenu()
{
menuItems= new MenuItem[MAX_ITEMS];
addItem( "Dinner Vegetarian", "Bacon", true,2.99);
addItem( "Dinner BLT ", "Bacon BLT", false,2.99);
addItem( "Dinner hotdog", "A hot dog", false,3.48);
}

public void addItem(String name,String description, boolean vegetarian, double price)
{
MenuItem item= new MenuItem(name,description,vegetarian,price);
if(numberOfItems<MAX_ITEMS)
{
menuItems[numberOfItems]=item;
numberOfItems++;
}
else
System.out.println( "Sorry ,menu is full");
}

public Iterator createIterator()
{
return  new DinerMenuIterator(menuItems);
}


}
利用ArrayList存储对象的具体集合
package com.whut.iterator;

import java.util.ArrayList;
import java.util.Iterator;
public class PancakeHouseMenu  implements Menu{

private ArrayList menuItems;

public PancakeHouseMenu()
{
menuItems= new ArrayList();
addItem( "K&B panckage breakfast", "pancakes with scramed eggs and toast", true,2.99);
addItem( "Regular panckage breakfast", "pancakes with fried eggs ", false,2.99);
addItem( "Blueberry breakfast", "pancakes made with fresh blueberry ", true,3.48);
addItem( "Waffles", "waffles, with your choice", true,3.59);
}

public void addItem(String name,String description, boolean vegetarian, double price)
{
MenuItem item= new MenuItem(name,description,vegetarian,price);
menuItems.add(item);
}
public Iterator createIterator()
{
return menuItems.iterator();
}
}
利用HashMap存储对象的具体集合
package com.whut.iterator;

import java.util.HashMap;
import java.util.Iterator;

public class CoffeeMenu  implements Menu{
private HashMap menuItems= new HashMap(); 
public CoffeeMenu()
{
addItem( "Coffee Burger" , "veggie burger on", true,3.99);
addItem( "Coffee Soup", "A cup of the soup", false,3.69);
addItem( "Coffee Burrito", "A large burrito", true,4.29);
}

public void addItem(String name,String description, boolean vegetarian, double price)
{
MenuItem item= new MenuItem(name,description,vegetarian,price);
menuItems.put(item.getName(),item);
}

@Override
public Iterator createIterator() {
// TODO Auto-generated method stub
//直接返回一个迭代器
return menuItems.values().iterator();
}
}
由于为了统一数组和ArrayList和HashMap的遍历方法,需要为数组建立一个迭代器
package com.whut.iterator;

import java.util.Iterator;

public class DinerMenuIterator  implements Iterator {

private MenuItem[] items;
private int position=0;//存放当前遍历的坐标

public DinerMenuIterator(MenuItem[] items)
{
this.items=items;
}

public  boolean hasNext() {
if(position>=items.length || items[position]== null)
return  false;
else
return  true;
}

public Object next() {
MenuItem menuItem=items[position];
position=position+1;
return menuItem;
}

public  void remove() {

if(position<=0)
throw  new IllegalStateException( "You can't remove an item at least");
if(items[position]!= null)
{
for( int i=position-1;i<items.length-1;i++)
items[i]=items[i+1];
items[items.length-1]= null;
}
}

}
提供一个来测试
package com.whut.iterator;
import java.util.Iterator;
public  class Waitress {

private Menu diner;
private Menu house;
private Menu cafe;
public Waitress(Menu diner,Menu house,Menu cafe)
{
this.diner=diner;
this.house=house;
this.cafe=cafe;
}

public void printMenu()
{
Iterator houseIterator=house.createIterator();
Iterator dinerIterator=diner.createIterator();
Iterator cafeIterator=cafe.createIterator();
System.out.println( "-------houseMenu--------");
printMenuItem(houseIterator);
System.out.println();

System.out.println( "-------dinnerMenu--------");
printMenuItem(dinerIterator);
System.out.println();

System.out.println( "-------coffeeMenu--------");
printMenuItem(cafeIterator);
}

private  void printMenuItem(Iterator iterator)
{
while(iterator.hasNext())
{
MenuItem menuItem=(MenuItem)iterator.next();
System.out.print(menuItem.getName()+ "_||_"+menuItem.getPrice()
+ "_||_"+menuItem.getDescription());
System.out.println();
}
}
}
设计原则: 一个类应该只有一个引起变化的原因。
组合模式
组合模式定义为允许你将对象组合树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及组合对象。
组合模式,能够让我们用树形方式创建对象的结构,树里面包含了组合以及个别对象。我们可以把相同的操作应用到组合对象和个别对象中。
在这种模式中,组合对象是可以包含个别对象的,而个别对象就是树形结构中的叶子节点。
一般利用组合模式,组合对象和个别对象均要实现同样的接口。组合模式应用场景主要是在当有多个对象的时候,他们彼此之间有“整体/部分”的关系,并且想要给客户一种一致的方法来对待这些对象的时候,就需要这种模式。组合模式能够使的客户不再担心面对的是组合对象或者个别对象,他们只需要对整个结构调用一个方法就可以执行所需要的遍历操作了
代码实例:
组合对象和个别对象均要实现相同接口
package com.whut.composite;

import java.util.ArrayList;
import java.util.Iterator;

//组合需要和叶子节点一样实现相同的接口
public class Flock  implements Quackable {

private ArrayList quackers= new ArrayList();

public void add(Quackable quacker)
{
quackers.add(quacker);
}
//通过实现相同的接口,就能保证每次循环遍历完所有的单个对象和对象集合
@Override
public void quack() {
// TODO Auto-generated method stub
Iterator iterator=quackers.iterator();
while(iterator.hasNext())
{
Quackable quacker=(Quackable) iterator.next();
quacker.quack();//注意这里
}
}

}
小技巧:
在我们设计类的时候,如果有些方法只是针对某一些子类型使用,而有一些针对其它子类型使用,为了防止各个子类非法去实现不属于自己的方法,可以在抽象类中的方法中直接throw new UnsupportedOperationException()。这样子类如果不需要该方法,就直接继承默认的。


本文转自 zhao_xiao_long 51CTO博客,原文链接:http://blog.51cto.com/computerdragon/1168807

相关文章
|
9天前
|
设计模式 存储 安全
「全网最细 + 实战源码案例」设计模式——组合模式
组合模式(Composite Pattern)是一种结构型设计模式,用于将对象组合成树形结构以表示“部分-整体”的层次结构。它允许客户端以一致的方式对待单个对象和对象集合,简化了复杂结构的处理。组合模式包含三个主要组件:抽象组件(Component)、叶子节点(Leaf)和组合节点(Composite)。通过这种模式,客户端可以统一处理简单元素和复杂元素,而无需关心其内部结构。适用于需要实现树状对象结构或希望以相同方式处理简单和复杂元素的场景。优点包括支持树形结构、透明性和遵循开闭原则;缺点是可能引入不必要的复杂性和过度抽象。
65 22
|
3月前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
|
3月前
|
设计模式 Java Kotlin
Kotlin教程笔记(54) - 改良设计模式 - 迭代器模式
Kotlin教程笔记(54) - 改良设计模式 - 迭代器模式
58 2
|
3月前
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
54 4
|
4月前
|
设计模式 Java 程序员
[Java]23种设计模式
本文介绍了设计模式的概念及其七大原则,强调了设计模式在提高代码重用性、可读性、可扩展性和可靠性方面的作用。文章还简要概述了23种设计模式,并提供了进一步学习的资源链接。
91 0
[Java]23种设计模式
|
3月前
|
设计模式 Java Kotlin
Kotlin - 改良设计模式 - 迭代器模式
Kotlin - 改良设计模式 - 迭代器模式
38 0
|
4月前
|
设计模式 Java 开发者
Kotlin教程笔记(54) - 改良设计模式 - 迭代器模式
本教程详细讲解Kotlin语法,适合希望深入了解Kotlin的开发者。对于快速学习Kotlin的用户,推荐查看“简洁”系列教程。本文重点介绍迭代器模式,通过具体示例展示了如何在Kotlin中实现迭代器模式,包括使用Iterator、Iterable接口及重载iterator运算符的方法。
44 4
|
4月前
|
设计模式 Java 开发者
Kotlin教程笔记(54) - 改良设计模式 - 迭代器模式
本教程详细讲解了Kotlin中的迭代器模式,包括如何通过实现Iterator和Iterable接口以及重载iterator运算符来实现可遍历的自定义集合。示例展示了如何创建一个图书集类,并通过不同方式使其支持遍历操作,适合希望深入了解Kotlin迭代器模式的开发者。
46 3
|
4月前
|
设计模式 Java Kotlin
Kotlin学习笔记 - 改良设计模式 - 迭代器模式
Kotlin学习笔记 - 改良设计模式 - 迭代器模式
45 2
|
3月前
|
设计模式 JavaScript Java
Java设计模式:建造者模式详解
建造者模式是一种创建型设计模式,通过将复杂对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。本文详细介绍了建造者模式的原理、背景、应用场景及实际Demo,帮助读者更好地理解和应用这一模式。
108 0