jtahstu的博客

root@jtahstu.com   Github   英文博客  

最新碎语:以后没事写写小的知识点吧

您的位置:jtahstu的博客 >笔记> 设计模式从入门到放弃 - 迭代器模式

设计模式从入门到放弃 - 迭代器模式

迭代器模式定义

    提供一种方法顺序访问一个聚合对象中的各个元素,而不是暴露其内部的表示。

迭代器模式结构与分析

UML类图

迭代器模式由以下角色组成:
   迭代器角色(Iterator):迭代器角色负责定义访问和遍历元素的接口。
   具体迭代器角色(Concrete Iterator):具体迭代器角色要实现迭代器接口,并要记录遍历中的当前位置。
   容器角色(Container):容器角色负责提供创建具体迭代器角色的接口。
   具体容器角色(Concrete Container):具体容器角色实现创建具体迭代器角色的接口——这个具体迭代器角色于该容器的结构相关。

迭代器模式示例代码

//Iterator.java
public interface Iterator {

	// 遍历到下一个元素
	public Object next();

	// 是否已经遍历到尾部
	public boolean hasNext();

	// 删除当前指向的元素
	public boolean remove();
}

//ConcreteIterator.java
public class ConcreteIterator implements Iterator {
	private Vector vector = new Vector();
	// 定义当前游标
	public int cursor = 0;

	@SuppressWarnings("unchecked")
	public ConcreteIterator(Vector _vector) {
		this.vector = _vector;
	}

	// 判断是否到达尾部
	public boolean hasNext() {
		if (this.cursor == this.vector.size()) {
			return false;
		} else {
			return true;
		}
	}

	// 返回下一个元素
	public Object next() {
		Object result = null;

		if (this.hasNext()) {
			result = this.vector.get(this.cursor++);
		} else {
			result = null;
		}
		return result;
	}

	// 删除当前元素
	public boolean remove() {
		this.vector.remove(this.cursor);
		return true;
	}

}

//Aggregate.java
public interface Aggregate {

	// 是容器必然有元素的增加
	public void add(Object object);

	// 减少元素
	public void remove(Object object);

	// 由迭代器来遍历所有的元素
	public Iterator iterator();
}

//ConcreteAggregate.java
public class ConcreteAggregate implements Aggregate {
	// 容纳对象的容器
	private Vector vector = new Vector();

	// 增加一个元素
	public void add(Object object) {
		this.vector.add(object);
	}

	// 返回迭代器对象
	public Iterator iterator() {
		return new ConcreteIterator(this.vector);
	}

	// 删除一个元素
	public void remove(Object object) {
		this.remove(object);
	}

}

//Client.java
public class Client {
	
	public static void main(String[] args) {
		//声明出容器
		Aggregate agg = new ConcreteAggregate();
		
		
		//产生对象数据放进去
		agg.add("abc");
		agg.add("aaa");
		agg.add("1234");
		
		//遍历一下
		Iterator iterator = agg.iterator();
		while(iterator.hasNext()){
			System.out.println(iterator.next());
		}
	}
}

案例uml图

案例代码

//IProject.java
public interface IProject {

	// 增加项目
	public void add(String name, int num, int cost);

	// 从老板这里看到的就是项目信息
	public String getProjectInfo();

	// 获得一个可以被遍历的对象
	public IProjectIterator iterator();
}

//IProjectIterator.java
public interface IProjectIterator extends Iterator {

}

//Project.java
public class Project implements IProject {
	// 定义一个项目列表,说有的项目都放在这里
	private ArrayList<IProject> projectList = new ArrayList<IProject>();

	// 项目名称
	private String name = "";

	// 项目成员数量
	private int num = 0;

	// 项目费用
	private int cost = 0;

	public Project() {

	}

	// 定义一个构造函数,把所有老板需要看到的信息存储起来
	private Project(String name, int num, int cost) {
		// 赋值到类的成员变量中
		this.name = name;
		this.num = num;
		this.cost = cost;
	}

	// 增加项目
	public void add(String name, int num, int cost) {
		this.projectList.add(new Project(name, num, cost));
	}

	// 得到项目的信息
	public String getProjectInfo() {
		String info = "";

		// 获得项目的名称
		info = info + "项目名称是:" + this.name;
		// 获得项目人数
		info = info + "\t项目人数: " + this.num;
		// 项目费用
		info = info + "\t 项目费用:" + this.cost;

		return info;
	}

	// 产生一个遍历对象
	public IProjectIterator iterator() {
		return new ProjectIterator(this.projectList);
	}

}

//ProjectIterator.java
public class ProjectIterator implements IProjectIterator {

	// 所有的项目都放在这里ArrayList中
	private ArrayList<IProject> projectList = new ArrayList<IProject>();

	private int currentItem = 0;

	// 构造函数出入projectList
	public ProjectIterator(ArrayList<IProject> projectList) {
		this.projectList = projectList;
	}

	// 判断是否还有元素,必须实现
	public boolean hasNext() {
		// 定义一个返回值
		boolean b = true;
		if (this.currentItem >= projectList.size() || this.projectList.get(this.currentItem) == null) {
			b = false;
		}
		return b;
	}

	// 取得下一个值
	public IProject next() {
		return (IProject) this.projectList.get(this.currentItem++);
	}

	// 删除一个对象
	public void remove() {
		// 暂时没有使用到
	}

}

//Boss.java
public class Boss {

	public static void main(String[] args) {
		// 定义一个List,存放所有的项目对象
		IProject project = new Project();

		// 增加星球大战项目
		project.add("星球大战项目ddddd", 10, 100000);
		// 增加扭转时空项目
		project.add("扭转时空项目", 100, 10000000);
		// 增加超人改造项目
		project.add("超人改造项目", 10000, 1000000000);

		// 这边100个项目
		for (int i = 4; i < 104; i++) {
			project.add("第" + i + "个项目", i * 5, i * 1000000);
		}

		// 遍历一下ArrayList,把所有的数据都取出
		IProjectIterator projectIterator = project.iterator();
		while (projectIterator.hasNext()) {
			IProject p = (IProject) projectIterator.next();
			System.out.println(p.getProjectInfo());

		}

	}
}

PHP代码示例

<?php
//抽象迭代器
abstract class IIterator {
	public abstract function First();
	public abstract function Next();
	public abstract function IsDone();
	public abstract function CurrentItem();
}

//具体迭代器
class ConcreteIterator extends IIterator {
	private $aggre;
	private $current = 0;
	public function __construct(array $_aggre) {
		$this -> aggre = $_aggre;
	}

	//返回第一个
	public function First() {
		return $this -> aggre[0];
	}

	//返回下一个
	public function Next() {
		$this -> current++;
		if ($this -> current < count($this -> aggre)) {
			return $this -> aggre[$this -> current];
		}
		return false;
	}

	//返回是否IsDone
	public function IsDone() {
		return $this -> current >= count($this -> aggre) ? true : false;
	}

	//返回当前聚集对象
	public function CurrentItem() {
		return $this -> aggre[$this -> current];
	}

}

$iterator = new ConcreteIterator( array('周杰伦', '王菲', '周润发'));
$item = $iterator -> First();
echo $item . "<br/>";
while (!$iterator -> IsDone()) {
	echo "{$iterator->CurrentItem()}:请买票!<br/>";
	$iterator -> Next();
}

迭代器模式的优缺点

优点:

    简化了遍历方式,对于对象集合的遍历,还是比较麻烦的,对于数组或者有序列表,我们尚可以通过游标来取得,但用户需要在对集合了解很清楚的前提下,自行遍历对象,但是对于hash表来说,用户遍历起来就比较麻烦了。而引入了迭代器方法后,用户用起来就简单的多了。

    可以提供多种遍历方式,比如说对有序列表,我们可以根据需要提供正序遍历,倒序遍历两种迭代器,用户用起来只需要得到我们实现好的迭代器,就可以方便的对集合进行遍历了。

    封装性良好,用户只需要得到迭代器就可以遍历,而对于遍历算法则不用去关心

    迭代器简化了聚合类。

缺点:

    对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐,大家可能都有感觉,像ArrayList,我们宁可愿意使用for循环和get方法来遍历集合。

    增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,增加了系统复杂性。

迭代器模式的适用场景

    访问一个聚合对象的内容而无须暴露他的内部表示。

    需要为聚合对象提供多种遍历方式。

    为遍历不同的聚合结构提供统一的接口。

    迭代器模式是与集合共生共死的,一般来说,我们只要实现一个集合,就需要同时提供这个集合的迭代器,就像java中的Collection,List、 Set、Map等,这些集合都有自己的迭代器。假如我们要实现一个这样的新的容器,当然也需要引入迭代器模式,给我们的容器实现一个迭代器。

    但是,由于容器与迭代器的关系太密切了,所以大多数语言在实现容器的时候都给提供了迭代器,并且这些语言提供的容器和迭代器在绝大多数情况下就可以满足我 们的需要,所以现在需要我们自己去实践迭代器模式的场景还是比较少见的,我们只需要使用语言中已有的容器和迭代器就可以了

    引用《设计模式之禅》的话就是

        "如果你是做Java开发,尽量不要自己写迭代器模式!省省吧,使用Java提供的Iterator一般就能满足你的要求了。"

参考

  1. CSDN http://blog.csdn.net/zhengzhb/article/details/7610745
  2. 《设计模式之禅》
  3. CSDN2 http://blog.csdn.net/jhq0113/article/details/46418697
  4. 课本

---

本文章采用 知识共享署名2.5中国大陆许可协议 进行许可,欢迎转载,演绎或用于商业目的。

---

二维码加载中...

扫一扫移动端访问O(∩_∩)O

发表评论

95 + 61 =
路人甲 表情
看不清楚?点图切换 Ctrl+Enter快速提交
正在加载中……