设计模式——迭代器模式

设计模式——迭代器模式

本篇博文通过学习尚硅谷韩老师《设计模式》所做,在此非常感谢!

概述

基本介绍

  • 迭代器模式(Iterator Pattern)是常用的设计模式,属于行为型模式;
  • 如果我们的集合元素是用不同的方式实现的,有数组,还有 Java的集合类,或者还有其他方式,当客户端要遍历这些集合元素的时候就要使用多种遍历方式,而且还会暴露元素的内部结构,可以考虑使用迭代器模式解决;
  • 迭代器模式,提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层表示,即:不暴露其内部的结构;

细节和注意事项

  • 提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了;
  • 隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成;
  • 提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任原则)。在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,这样一来集合改变的话,只影响到聚合对象。而如果遍历方式改变的话,只影响到了迭代器;
  • 当要展示一组相似对象,或者遍历一组相同对象时使用, 适合使用迭代器模式;
  • 但是每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类;

UML
在这里插入图片描述

问题引入

编写程序展示一个学校院系结构:需求是这样,要在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系;这里我们作为演示提供2个学院

分析
如果我们采用传统的方式,学校类的子类为学院类学院类的子类为下辖的专业类,这样一来,整个系统的结构就变成了树形的结构,继承的层数较高,而且不宜遍历打印;类过于庞大,一个专业就是一个类,而一个学院类下面又有多个专业类,一旦系统规模增大势必造成类爆炸
但是换种思路学院下的专业类是同一种类【因此我们可以把专业类直接在其对应的学院类内部使用数组的形式处理掉(包括增删改查等业务逻辑),除去原先的继承关系】;学校下的学院类属于同一种类,我们可以将这些类加入到List集合,对外部的这些类采用集合的方式进行增删改查等业务,此时对于该系统来说有两种类型的遍历(数组和集合),因此迭代器模式最为合适;

编码实现

UML

首先构建出UML图,如下:
在这里插入图片描述

编码

首先构建表示专业的专业类Department做为具体迭代器类内的元素,如下:

package edu.hebeu.element;

/**
 * 系别类
 * @author 13651
 *
 */
public class Department {
	private String name;
	private String desc;
	
	public Department(String name, String desc) {
		super();
		this.name = name;
		this.desc = desc;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getDesc() {
		return desc;
	}
	
	public void setDesc(String desc) {
		this.desc = desc;
	}
	
}

我们本例中的学院类提供两个,一个是ComputerCollege计算机学院类,另一个是MaterialCollege材料学院类,因此我们先创建出这两个类对应的迭代器类(同时实现Iterator接口类,让这两个类都能通过迭代器遍历自己下辖的专业类),如下

package edu.hebeu.iterator;

import java.util.Iterator;

import edu.hebeu.element.Department;

/**
 * 计算机学院(ComputerCollege)的 Iterator类
 * @author 13651
 *
 */
public class ComputerCollegeIterator implements Iterator<Object>{
	
	/**
	 * 指定要遍历的元素以什么形式存放
	 */
	private Department[] departments;
	private int position;
	
	public ComputerCollegeIterator(Department[] departments) {
		this.departments = departments;
	}

	/**
	 * 判断是否还有下一个元素
	 */
	@Override
	public boolean hasNext() {
		if(position >= departments.length || departments[position] == null) {
			return false;
		}
		return true;
	}

	/**
	 * 取出当前下标位置的元素
	 */
	@Override
	public Object next() {
		Department department = departments[position];
		position += 1;
		return department;
	}
	
	/**
	 * 删除元素,空实现
	 */
	@Override
	public void remove() {
	}

}

package edu.hebeu.iterator;

import java.util.Iterator;
import java.util.List;

import edu.hebeu.element.Department;

/**
 * 材料学院类(MaterialCollege)的 Iterator类
 * @author 13651
 *
 */
public class MaterialCollegeIterator implements Iterator<Object>{
	
	/**
	 * 指定要遍历的元素以什么形式存放
	 */
	private List<Department> departments;
	private int index = -1;
	
	public MaterialCollegeIterator(List<Department> departments) {
		this.departments = departments;
	}

	/**
	 * 判断还有没有下一个元素
	 */
	@Override
	public boolean hasNext() {
		if(index >= departments.size() - 1) {
			return false;
		} else {
			index += 1;
			return true;
		}
	}

	/**
	 * 返回指定位置的元素
	 */
	@Override
	public Object next() {
		return departments.get(index);
	}
	
	/**
	 * 删除元素,空实现
	 */
	@Override
	public void remove() {
	}
	
}

此时为了削减程序的耦合,我们应该先创建一个学院类的抽象类College来将学院的共性抽取

package edu.hebeu.aggregate;

import java.util.Iterator;

/**
 * 学院的接口
 * @author 13651
 *
 */
public interface College {
	
	/**
	 * 获取学院的名字
	 * @return
	 */
	String getName();
	
	/**
	 * 获取学院的描述
	 * @return
	 */
	String getDesc();
	
	/**
	 * 给学院添加系别
	 * @param name
	 * @param desc
	 */
	void addDepartment(String name, String desc);
	
	/**
	 * 创建并返回该集合类的Iterator
	 * @return
	 */
	Iterator<Object> createIterator();
}

接下来通过实现上述的接口创建具体的学院类计算机学院类ComputerCollege材料学院类MaterialCollege并为每个学院添加其下辖的专业,如下:

package edu.hebeu.aggregate;

import java.util.Iterator;

import edu.hebeu.element.Department;
import edu.hebeu.iterator.ComputerCollegeIterator;

/**
 * 计算机学院(ComputerCollege)类
 * @author 13651
 *
 */
public class ComputerCollege implements College {

	private Department[] departments; // 保存该类的系别对象
	private int num = 0;
	
	public ComputerCollege() {
		departments = new Department[10]; // 最大保存10个元素
		addDepartment("软件工程", "软件的开发");
		addDepartment("计算机科学技术", "偏向硬件方面的计算机学科");
		addDepartment("物联网", "万物互联");
		addDepartment("电气工程及其自动化", "电气、自动化、...");
	}

	@Override
	public String getName() {
		return "计算机学院";
	}

	@Override
	public String getDesc() {
		return "计算机相关的领域";
	}

	@Override
	public void addDepartment(String name, String desc) {
		departments[num] = new Department(name, desc);
		num += 1;
	}

	/**
	 * 创建该类的Iterator对象实例
	 */
	@Override
	public Iterator<Object> createIterator() {
		return new ComputerCollegeIterator(departments);
	}

}

package edu.hebeu.aggregate;

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

import edu.hebeu.element.Department;
import edu.hebeu.iterator.MaterialCollegeIterator;

/**
 * 材料学院(MaterialCollege)类
 * @author 13651
 *
 */
public class MaterialCollege implements College {
	
	private List<Department> departments;
	
	public MaterialCollege() {
		departments = new ArrayList<>();
		addDepartment("冶金工程", "金属冶炼");
		addDepartment("化工工程", "化工");
		addDepartment("应化", "应用化学");
		addDepartment("复材工程", "复合材料");
	}

	@Override
	public String getName() {
		return "材料学院";
	}

	@Override
	public String getDesc() {
		// TODO Auto-generated method stub
		return "材料类的学院";
	}

	@Override
	public void addDepartment(String name, String desc) {
		departments.add(new Department(name, desc));
	}

	@Override
	public Iterator<Object> createIterator() {
		return new MaterialCollegeIterator(departments);
	}

}

此时,迭代器模式搭建的项目的主体就完成了
我们为了更好的遍历,抽取出一个OutputInfo类来专门处理打印所有学院和其下辖专业的逻辑

package edu.hebeu;

import java.util.Iterator;
import java.util.List;

import edu.hebeu.aggregate.College;
import edu.hebeu.element.Department;

public class OutputInfo {
	
	/**
	 * 学院的集合
	 */
	private List<College> colleges;
	
	public OutputInfo(List<College> colleges) {
		this.colleges = colleges;
	}
	
	/**
	 * 输出全部的学院和其下的全部系别
	 */
	public void print() {
		Iterator<College> collegesIterator = colleges.iterator();
		while(collegesIterator.hasNext()) {
			College college = collegesIterator.next(); // 获取该学院对象
			System.out.println("-------------------学院:" + college.getName() + "-------------------");
			System.out.println("					描述:" + college.getDesc());
			
			// 调用该学院的printDepartment()方法
			printDepartment(college.createIterator());
		}
	}
	
	/**
	 * 输出系别
	 * @param iterator
	 */
	private void printDepartment(Iterator<Object> iterator) {
		while(iterator.hasNext()) {
			Department department = (Department) iterator.next();
			System.out.println("# " + department.getName() + "---" + department.getDesc());
		}
	}
	
}

此时,系统整体就完成了,我们编写客户端来进行测试,如下:

package edu.hebeu;

import java.util.ArrayList;
import java.util.List;

import edu.hebeu.aggregate.College;
import edu.hebeu.aggregate.ComputerCollege;
import edu.hebeu.aggregate.MaterialCollege;

public class Client {
	public static void main(String[] args) {
		
		// 创建学院的集合对象实例
		List<College> colleges = new ArrayList<>();
		
		// 创建学院对象
		ComputerCollege computerCollege = new ComputerCollege();
		MaterialCollege materialCollege = new MaterialCollege();
		
		// 将学院对象添加入学院集合
		colleges.add(computerCollege);
		colleges.add(materialCollege);
		
		// 遍历
		OutputInfo outputInfo = new OutputInfo(colleges);
		outputInfo.print();
		
	}
}

测试

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值