设计模式之迭代模式

1.引子

假如部门十个人组织一次秋游,由于人数较少所以计划集合后集体坐公交前往目的地。当日从起始站来了一辆空公交车,小伙伴上车坐好后,票务员来到每个人的身边开始收车票。这一个简单的场景就包含迭代模式。

场景内涉及到公交车十个人的小集体还有票务员(司机看做公交车的一部分吧)。可以把场景抽象一下:
①公交车是一个聚集类(可容纳十个人的小集体还有一名票务员);
②十个人的小集体可以认为是一个长度为十的数组;
③票务员是自带有遍历整个公交内乘客的迭代类,它知道公交内坐了多少人,哪个座位坐了谁等。

用实例代码表示就是:

1.1 普通版

上车乘客信息:

public class Person{
	private String name;

	public String getName() {
		return name;
	}

	public Person(String name){
		this.name = name;
	}

	@Override
	public String toString() {
		return "Person.name=" + name;
	}
}

注意:假设只需要名字就行,并通过构造函数注入乘客姓名;

公交类:

public class Bus {
	
	private Person[] persons;   // 上车乘客是一个数组
	
	public Bus(Person[] persons){
		this.persons = persons;
	}
	
	public Conductor createConductor(){
		return new Conductor(this);   // 售票员
	}
	
	// 获取上车人数
	public int size(){
		if (persons != null) {
			return persons.length;
		}else {
			return 0;
		}
	}
	
	// 获取车内index位置处乘客的信息
	public Person getPerson(int index){
		if (persons != null && persons.length > 0){
			return persons[index];
		} else {
			return null;
		}
	}
	
}

注意:公交车聚集类有一个制造迭代器的工厂方法。

票务员类:

public class Conductor {
	private Bus bus;
	private int index;  // 当前第index个顾客
	private int size;   // 总共有size个顾客
	
	public Conductor(Bus bus){
		this.bus = bus;
		this.size = bus.size();
		this.index = 0;
	}
	
	// 从第一个客户售票
	public void first(){
		index = 0;
	}
	
	// 下一个客户
	public void next(){
		index++;
	}
	
	// 是否最后一个客户
	public boolean isLast(){
		return index >= size;
	}
	
	// 获取当前位置的客户信息
	public Person currentPerson(){
		return bus.getPerson(index); 
	}
}

注意:票务员通过公交车的getPerson()方法获得乘客信息;通过first(),next(),isLast()方法遍历乘客;

测试类:

public class Main {
	public static void main(String[] args) {
		// 十位小伙伴
		Person[] persons = new Person[10];
		for (int i = 0; i < persons.length; i++) {
			persons[i] = new Person("a"+i);
		}
		 
		Bus bus = new Bus(persons);    // 上车
		Conductor conductor = bus.createConductor();   // 售票员
		// 售票员遍历每一个乘客来收费
		while (!conductor.isLast()) {
			Person person = conductor.currentPerson();
			conductor.next();
			System.out.println(person);
		}
	}
}

运行结果:

Person.name=a0
Person.name=a1
Person.name=a2
Person.name=a3
Person.name=a4
Person.name=a5
Person.name=a6
Person.name=a7
Person.name=a8
Person.name=a9

假设该车的售票员小B今天生病了,临时换了另外一个售货员小C,在这个例子里面不仅需要新建小C类,还需要修改Bus类的createConductor()方法;同样,如果此辆公交车坏了,需要新换一辆公交车,即需要新建Bus类还需要修改Conductor类;违背了“开闭原则”。所以可以把公交车和售票员抽象出来,后期只需要扩展就行。

1.2 抽象版

抽象公交类:

public abstract class AbstractBus {
	protected abstract AbstractConductor createConductor();
}

抽象售票员:

public interface AbstractConductor {

	void first();  // 从第一个客户售票
	void next();   // 下一个客户
	boolean isLast();   // 是否最后一个客户
	Person currentPerson();  // 获取当前位置的客户信息
}

实体公交类、实体售票员分别继承抽象公交类、实现抽象售票员接口;测试类基本不变。

类似于这种遍历方式的就是迭代模式。

2.迭代模式的原理

从上面的实际例子可知,公交车是一个聚集类;售票员是对公交车内Person属性进行遍历。在客户端中,我们并不知道公交车上有多少person,遍历完全由售票员来完成,进而隐藏了遍历的细节。

3.迭代模式的使用场景

当一个聚集对象需要被遍历,且被遍历的方式需要与聚集对象解耦的情况下,迭代器模式是不二之选。由于java语言本身带有众多集合类,如List、Set、Map等,这些集合内部都有迭代器,所以迭代模式很少用,除非自己定义一个容器。

4.迭代模式的特点

迭代器模式分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样做的好处就是既可以做到不暴露集合的内部结构,又可以让外部代码透明地访问集合内部的数据

5.参考资料

https://blog.csdn.net/jason0539/article/details/45070441
《大话设计模式》

6.源码

https://download.csdn.net/download/nobody_1/10821374

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值