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

本文介绍了迭代器模式和组合模式,阐述了迭代器模式的使用,包括显示迭代和隐式迭代,并探讨了其优点。同时,解释了组合模式的概念,通过菜单的例子帮助理解。迭代器模式与组合模式结合,用于管理鸭群,允许递归访问多层次的鸭子集合。通过实现统一接口,可以轻松打印出不同层次的鸭群,展示了两种模式在实际问题中的强大能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

迭代器模式和组合模式

什么是迭代器模式:这个模式主要是基于迭代器的扩展设计而形成的一种模式,迭代器的常用方法是hasNext()和next()方法,前者判断有没有下一个元素,后者表示取出下一个元素,在Java集合框架中,我们可以发现,其实所有集合的超类Collection实现了Iterator接口:public interface Collection extends Iterable
也就是说,所有的集合类都可以通过迭代器来进行迭代,一般获取迭代器的方法是集合的对象名“.iterator()”就可以得到一个迭代器对象,然后就可以通过迭代器进行迭代。
显示迭代和隐式迭代:上述的一种获取迭代器的方法是一种显示迭代器,就是我们已经实例化了迭代器的对象,而隐式迭代器是通过for循环来实现的:for(int a: array){} 。类似于这种结构,第一部分是其中的元素类型,第二部分是遍历的集合对象。这两种方式在实际上都是迭代器。
迭代器模式的优点:迭代器的特点是它只负责遍历集合,而不关心集合的具体内容,给迭代器一个集合的引用就可以了,这有利于迭代器的代码与集合的赋值代码解耦。
迭代器模式的应用
1、同层:迭代器可以实现整合不同的集合,在同一个方法中打印所有持有的集合的信息,使用方法很简单,在一个打印的方法中实例化每个集合的迭代器然后循环打印即可。
2、不同层:迭代器可以以一段稳定的代码实现对有包含关系的集合的递归访问。这也是它和组合模式的结合应用,在后面我们会介绍它和组合模式的结合,因为两种模式一般同时出现,相辅相成。
什么是组合模式:组合模式就是指通过集合来对元素进行包含,并且允许多层的包含关系,利用组合模式,可以实现对有包含关系的多层次的集合的管理。这样说似乎很抽象,我们只要记住一个例子就可以理解组合模式了。比如一个菜单的例子,一个总菜单下可以有多个子菜单,每个子菜单也可以有它们的子菜单,一层层下去,每个菜单都有自己的集合,其中每个集合的元素也可以是一个集合。
迭代器模式和组合模式的合作:按照上述的菜单的例子,当我们获得了一个有多层嵌套的集合关系时,如何去遍历,此时就需要用到迭代器,组织一段迭代器的代码,实现递归调用,顶层菜单调用可以打印出它的所有的下属菜目,用一个子菜单来调用这个方法可以打印出属于它的子菜目。前提是子菜单和顶层菜单都实现了一个相同的接口。

利用组合模式和迭代器模式实现鸭群

所有鸭子都实现这个接口,都有鸭叫这个方法:

public interface Quackable {		
    public abstract void  quack();
}

三种实现了该接口的鸭子类

public class RedHeadDuck implements Quackable{	
	public void quack() {
		System.out.println("Quack");		
	}
}
public class DuckCall implements Quackable{
	public void quack() {
	      System.out.println("Kwak");		
	}
}
public class RubberDuck implements Quackable{
	public void quack() {
		System.out.println("Squeak");		
	}
}

鸭群类(注意,它也实现了鸭叫的接口):

public class FlockOfDucks implements Quackable{
    ArrayList<Quackable> array;	
	public FlockOfDucks(){
		array=new ArrayList<Quackable>();
	}
	public void add(Quackable duck){
		array.add(duck);
	}	
	public void quack() {
		Iterator<Quackable> iterator=array.iterator();
		while(iterator.hasNext()){
			Quackable duck=iterator.next();
			duck.quack();
		}
	}
}

测试类

public class Test {		
	public static void main(String[] args){
		DuckCall duckCall=new DuckCall();
		RedHeadDuck redHeadDuck=new RedHeadDuck();
		RubberDuck rubberDuck=new RubberDuck();		
		FlockOfDucks flock=new FlockOfDucks();
		flock.add(rubberDuck);
		flock.add(redHeadDuck);
		flock.add(duckCall);		
		FlockOfDucks flock2=new FlockOfDucks();
		RubberDuck rubberDuck1=new RubberDuck();
		RubberDuck rubberDuck2=new RubberDuck();
		RubberDuck rubberDuck3=new RubberDuck();
		RubberDuck rubberDuck4=new RubberDuck();
		flock2.add(rubberDuck1);
		flock2.add(rubberDuck2);
		flock2.add(rubberDuck3);
		flock2.add(rubberDuck4);		
		flock.add(flock2);		
		flock.quack();		
		System.out.println("+++++++++++++++++++++++++=");		
		flock2.quack();		
	}
}

输出
在这里插入图片描述
**上面的代码实现了什么效果呢?**先建了一个鸭群的集合,加入了三只鸭子;然后又建了一个鸭群,加入了四只鸭子;再把这个鸭群加入到了第一个鸭群中,作为一个子集。输出第一个鸭群的时候,我们可以打印出所有的鸭子,输出第二个鸭群的时候,我们只能打印出第二个鸭群。这就是迭代模式和组合模式的好处,我们可以轻易获得任一层的子菜单而不用修改迭代器代码。最后再简单分析一下迭代的代码:

	public void quack() {
		Iterator<Quackable> iterator=array.iterator();
		while(iterator.hasNext()){
			Quackable duck=iterator.next();
			duck.quack();
		}
	}

如果调用这个quack()方法的是一个包含若干鸭子的集合,迭代器就会打印出每只鸭子的叫声;而如果其中有一个鸭子的子集,就会调用这个子集的quack()方法,相当于又重新进入了这个方法,不过这次得到的迭代器是这个子集集合的迭代器,迭代的是这个小鸭群的所有鸭子。如果有更多地层级,原理也都一样,一层层递归下去就是了。不管有多少层次,给它一个顶层鸭群的引用,调用quack()方法,就能打印出所有鸭子的叫声。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值