Behavioral pattern: analysis of iterator pattern

ITERATOR

Today is the tenth article of the design pattern learning series. What I want to learn today is the iterator pattern .

Start with questions

  1. What is the iterator pattern?
  2. What problem does iterator solve?
  3. Applicable scene?

definition

The iterator pattern provides a way to sequentially access the elements in an aggregate object without exposing its internal representation.

Insert picture description here

problem

An aggregate object, such as a list, array, tree structure, etc., should provide a way for others to access its elements without exposing the internal structure. In addition, for different needs, the aggregate object may be traversed in different ways. However, because the internal structure of the aggregate object is different, and the traversal method is different, it will cause a lot of annoyance to the user, because it is necessary to write different codes for different aggregate objects.

The iterator pattern can help you solve this problem. The key idea of ​​this pattern is to separate the access and traversal of the list from the list object and put it into an iterator . The iterator class defines an interface to access the aggregated elements. The iterator is responsible for tracking the current element; that is, it knows which elements have been traversed.

For example, today you need to use the depth-first algorithm to traverse the tree structure, tomorrow you may need the breadth first algorithm; next week, you may need other methods (such as random access to the elements in the tree).

On the other hand, client code that uses multiple collections may not care about the way the data is stored. However, because collections provide different ways to access elements, your code will have to be coupled with specific collection classes.

solution

At this time, you may need an iterator object, the relationship between them is as follows:

Insert picture description here

Before instantiating the iterator, the aggregate object to be traversed must be provided. Once you have an instance of the aggregate object iterator, you can sequentially access the elements of the list.

Iterator pattern class diagram

Insert picture description here

The above figure also shows that in order to make the client code not dependent on the specific aggregate object, the client cannot simply instantiate a creation iterator by himself, but let the aggregate object be responsible for creating the corresponding iterator. So the collection object provides an operation like createIterator.

It should be noted that the creation of iterators here is a Factory Method mode, have you found out?

applicability

The iterator pattern can be used to:

  • Access the content of an aggregate object without exposing its internal representation;
  • Support multiple traversal of aggregate objects;
  • Provide a unified interface for traversing different aggregation structures (ie, support polymorphic iteration);

The benefits

  1. It supports traversing a collection in different ways. Complex aggregations can be traversed in many ways. For example, code generation and semantic checking need to traverse the syntax analysis tree. Code generation can traverse the parse tree in middle order or preorder. The iterator pattern makes it easy to change the traversal algorithm: just replace the previous instance with a different iterator instance. You can also define your own subclasses of iterators to support new traversals.
  2. Iterators simplify the interface of aggregation. With the traversal interface of iterators, the aggregation itself no longer needs a similar traversal interface.
  3. There can be multiple traversals on the same aggregation. Each iterator maintains its own traversal state. So you can implement multiple traversals at the same time.

achieve

If we want to show the needs of all majors in all departments of a school, each department is independent, which means that the data structure used by each department may be different. Next we will use the iterator pattern to achieve, let's take a look together.

public class Client {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		//创建学院
		List<College> collegeList = new ArrayList<College>();
		
		ComputerCollege computerCollege = new ComputerCollege();
		InfoCollege infoCollege = new InfoCollege();
		
		collegeList.add(computerCollege);
		//collegeList.add(infoCollege);
		
		OutPutImpl outPutImpl = new OutPutImpl(collegeList);
		outPutImpl.printCollege();
	}

}
public interface College {
    
    
	
	public String getName();
	
	//增加系的方法
	public void addDepartment(String name, String desc);
	
	//返回一个迭代器,遍历
	public Iterator  createIterator();
}
public class ComputerCollege implements College {
    
    

	Department[] departments;
	int numOfDepartment = 0 ;// 保存当前数组的对象个数
	
	
	public ComputerCollege() {
    
    
		departments = new Department[5];
		addDepartment("Java专业", " Java专业 ");
		addDepartment("PHP专业", " PHP专业 ");
		addDepartment("大数据专业", " 大数据专业 ");
		
	}
	
	
	@Override
	public String getName() {
    
    
		// TODO Auto-generated method stub
		return "计算机学院";
	}

	@Override
	public void addDepartment(String name, String desc) {
    
    
		// TODO Auto-generated method stub
		Department department = new Department(name, desc);
		departments[numOfDepartment] = department;
		numOfDepartment += 1;
	}

	@Override
	public Iterator createIterator() {
    
    
		// TODO Auto-generated method stub
		return new ComputerCollegeIterator(departments);
	}

}
public class ComputerCollegeIterator implements Iterator {
    
    

	//这里我们需要Department 是以怎样的方式存放=>数组
	Department[] departments;
	int position = 0; //遍历的位置

	public ComputerCollegeIterator(Department[] departments) {
    
    
		this.departments = departments;
	}

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

	@Override
	public Object next() {
    
    
		// TODO Auto-generated method stub
		Department department = departments[position];
		position += 1;
		return department;
	}	
	//删除的方法,默认空实现
	public void remove() {
    
    
		
	}
}
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;
	}
}

public class InfoColleageIterator implements Iterator {
    
    

	
	List<Department> departmentList; // 信息工程学院是以List方式存放系
	int index = -1;//索引
	

	public InfoColleageIterator(List<Department> departmentList) {
    
    
		this.departmentList = departmentList;
	}

	//判断list中还有没有下一个元素
	@Override
	public boolean hasNext() {
    
    
		// TODO Auto-generated method stub
		if(index >= departmentList.size() - 1) {
    
    
			return false;
		} else {
    
    
			index += 1;
			return true;
		}
	}
	@Override
	public Object next() {
    
    
		// TODO Auto-generated method stub
		return departmentList.get(index);
	}
	//空实现remove
	public void remove() {
    
    
		
	}
}
public class InfoCollege implements College {
    
    

	List<Department> departmentList;
	
	
	public InfoCollege() {
    
    
		departmentList = new ArrayList<Department>();
		addDepartment("信息安全专业", " 信息安全专业 ");
		addDepartment("网络安全专业", " 网络安全专业 ");
		addDepartment("服务器安全专业", " 服务器安全专业 ");
	}
	
	@Override
	public String getName() {
    
    
		// TODO Auto-generated method stub
		return "信息工程学院";
	}

	@Override
	public void addDepartment(String name, String desc) {
    
    
		// TODO Auto-generated method stub
		Department department = new Department(name, desc);
		departmentList.add(department);
	}

	@Override
	public Iterator createIterator() {
    
    
		// TODO Auto-generated method stub
		return new InfoColleageIterator(departmentList);
	}
}
public class OutPutImpl {
    
    
	
	//学院集合
	List<College> collegeList;

	public OutPutImpl(List<College> collegeList) {
    
    
		
		this.collegeList = collegeList;
	}
	//遍历所有学院,然后调用printDepartment 输出各个学院的系
	public void printCollege() {
    
    
		
		//从collegeList 取出所有学院, Java 中的 List 已经实现Iterator
		Iterator<College> iterator = collegeList.iterator();
		
		while(iterator.hasNext()) {
    
    
			//取出一个学院
			College college = iterator.next();
			System.out.println("=== "+college.getName() +"=====" );
			printDepartment(college.createIterator()); //得到对应迭代器
		}
	}
	
	//输出 学院输出 系
	
	public void printDepartment(Iterator iterator) {
    
    
		while(iterator.hasNext()) {
    
    
			Department d = (Department)iterator.next();
			System.out.println(d.getName());
		}
	}
}


This article also involves a core design principle: single responsibility , a class should have only one cause of change.

The learning of design patterns needs to be practiced before they can be mastered. I hope that after understanding the idea of ​​the pattern, you can think about it in your usual code. Many people complain that there is no work content in the work. Crud all day, in fact, you might as well use the design pattern. Optimize your code to start.

End of this article! fighting

Personal public account

Insert picture description here

  • Friends who feel that they are writing well can bother to like and follow ;
  • If the article is incorrect, please point it out, thank you very much for reading;
  • I recommend everyone to pay attention to my official account, and I will regularly push original dry goods articles for you, and pull you into the high-quality learning community;
  • github address: github.com/coderluojust/qige_blogs

Guess you like

Origin blog.csdn.net/taurus_7c/article/details/107649552