In real life and programming, it is often necessary to access various elements in an aggregate object, such as the linked list traversal in the "data structure". The usual practice is to put the creation and traversal of the linked list in the same class, but this method is not conducive to the expansion of the program. If you want to change the traversal method, you must modify the program source code, which violates the "opening and closing principle".
Since it is not advisable to encapsulate traversal methods in aggregate classes, is it feasible to implement traversal methods by users without providing traversal methods in aggregate classes? The answer is equally undesirable, because this approach has two disadvantages:
Expose the internal representation of the aggregation class, making its data unsafe;
Increased the burden on customers.
The "iterator mode" can better overcome the above shortcomings. It inserts an iterator between the customer access class and the aggregation class, which separates the aggregation object from its traversal behavior, hides its internal details from the customer, and meets the "single responsibility principle" and "opening and closing principle". For example, the Collection, List, Set, Map, etc. in Java contain iterators.
Iterator mode is widely used in life, such as the conveyor belt in the logistics system. No matter what items are transported, they will be packed into boxes with a unified two-dimensional code. In this way, we don't need to care about what is in the box. We only need to check the sending destinations one by one during distribution. For another example, when we usually take transportation, we always swipe our card or face to enter the station, and we don't need to care about whether it is male or female, disabled or normal.
Definition and characteristics of pattern
Definition of iterator pattern: provide an object to access a series of data in an aggregate object sequentially without exposing the internal representation of the aggregate object. Iterator pattern is an object behavior pattern. Its main advantages are as follows.
Access the contents of an aggregate object without exposing its internal representation.
The traversal task is left to the iterator, which simplifies the aggregation class.
It supports traversing an aggregate in different ways, and you can even customize the subclass of the iterator to support new traversal.
Adding new aggregate classes and iterator classes is very convenient without modifying the original code.
It has good encapsulation and provides a unified interface for traversing different aggregation structures.
Its main disadvantage is that it increases the number of classes, which increases the complexity of the system to a certain extent.
In daily development, we hardly write iterators ourselves. Unless you need to customize an iterator corresponding to your own data structure, the API provided by the open source framework is fully sufficient.
Structure and implementation of pattern
The iterator pattern is realized by separating the traversal behavior of the aggregated object and abstracting it into an iterator class. Its purpose is to make the external code access the aggregated internal data transparently without exposing the internal structure of the aggregated object. Now let's analyze its basic structure and implementation method.
- Pattern structure
The iterator pattern mainly includes the following roles.
Abstract Aggregate role: defines interfaces for storing, adding, deleting Aggregate objects, and creating iterator objects.
Concrete aggregate role: implement the abstract aggregate class and return an instance of a concrete iterator.
Abstract Iterator role: defines the interface for accessing and traversing aggregation elements, usually including hasNext(), first(), next(), etc.
Concrete iterator role: implement the methods defined in the abstract iterator interface, complete the traversal of aggregate objects, and record the current location of traversal.
Its structure is shown in Figure 1.
- Implementation of pattern
The implementation code of iterator mode is as follows:
package net.biancheng.c.iterator; import java.util.*; public class IteratorPattern { public static void main(String[] args) { Aggregate ag = new ConcreteAggregate(); ag.add("Sun Yat-sen University"); ag.add("South China Institute of Technology"); ag.add("shaoguan university "); System.out.print("The aggregated contents include:"); Iterator it = ag.getIterator(); while (it.hasNext()) { Object ob = it.next(); System.out.print(ob.toString() + "\t"); } Object ob = it.first(); System.out.println("\nFirst: " + ob.toString()); } } //Abstract aggregation interface Aggregate { public void add(Object obj); public void remove(Object obj); public Iterator getIterator(); } //Specific aggregation class ConcreteAggregate implements Aggregate { private List<Object> list = new ArrayList<Object>(); public void add(Object obj) { list.add(obj); } public void remove(Object obj) { list.remove(obj); } public Iterator getIterator() { return (new ConcreteIterator(list)); } } //Abstract iterator interface Iterator { Object first(); Object next(); boolean hasNext(); } //Concrete iterator class ConcreteIterator implements Iterator { private List<Object> list = null; private int index = -1; public ConcreteIterator(List<Object> list) { this.list = list; } public boolean hasNext() { if (index < list.size() - 1) { return true; } else { return false; } } public Object first() { index = 0; Object obj = list.get(index); ; return obj; } public Object next() { Object obj = null; if (this.hasNext()) { obj = list.get(++index); } return obj; } }
Application examples of pattern
[example 1] write a program to browse Wuyuan tourism landscape map in iterator mode.
Analysis: there are many scenic spots and historic sites in Wuyuan. It is appropriate to design a program to view the pictures of relevant scenic spots (click here to download the pictures of scenic spots to be displayed in this example) and a brief introduction, and use the "iterator mode" design.
First, design a Wuyuan scenic spot class to save the name and introduction of each picture; Another scenic spot set interface is designed. It is an abstract aggregation class, which provides methods to add and delete Wuyuan scenic spots, as well as methods to obtain iterators.
Then, define a Wuyuan scenic spot set class, which is a concrete aggregation class, use ArrayList to save all scenic spot information, and implement the abstract methods in the parent class; Then define the abstract iterator interface of Wuyuan scenic spot, which contains the relevant methods to view the scenic spot information.
Finally, the wyviewspotiterator class of Wuyuan scenic spot is defined, which implements the abstract method of the parent class; The client program is designed as a window program, which initializes the data in the Wuyuan scenic spot set and implements the ActionListener interface. It checks the information of Wuyuan scenic spot through the Wuyuan scenic spot iterator. Figure 2 shows its structure.
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; public class PictureIterator { public static void main(String[] args) { new PictureFrame(); } } //Photo frame class class PictureFrame extends JFrame implements ActionListener { private static final long serialVersionUID = 1L; ViewSpotSet ag; //Wuyuan scenic spot collection interface ViewSpotIterator it; //Wuyuan scenic spot iterator interface WyViewSpot ob; //Wuyuan scenic spots PictureFrame() { super("Some landscapes of Wuyuan, the most beautiful village in China"); this.setResizable(false); ag = new WyViewSpotSet(); ag.add(new WyViewSpot("Jiangwan", "Jiangwan scenic spot is a national scenic spot in Wuyuan A There are a large number of ancient buildings in the scenic spot, such as Xiaojiang ancestral temple, Yongsi street, Teng family's old house, Wuyuan family, Xiangxian garden, Baigongfang and so on.")); ag.add(new WyViewSpot("Li Keng", "Li Keng Village is an ancient village mainly inhabited by Li surname. It is a national 4 village A The first-class scenic spot, with unique architectural style, is a famous Huizhou architecture, giving people a feeling of quiet and harmony.")); ag.add(new WyViewSpot("Sixiyan Village", "Sixiyan village is located in Sikou Town, Wuyuan County. It was founded in the fifth year of Qingyuan in the Southern Song Dynasty (1199). At that time, Yu, the founder of the village, was famous for (FISH) siqingxi water.")); ag.add(new WyViewSpot("Xiaoqi Village", "Xiaoqi has the reputation of "the first village of Chinese tea culture" and "national ecological demonstration village". Most of the village houses are buildings of the Qing Dynasty with different styles. The small and medium-sized alleys of the village are paved with bluestones, twists and turns, like a chess game.")); ag.add(new WyViewSpot("Jujing Village", "The shape of Jujing village is surrounded by mountains and water, and the river is in a large semicircle shape. It surrounds the village for nearly one week, surrounded by mountains, which is in line with the Chinese Bagua design of "water in front of mountains", and the local people call it "washbasin village".")); ag.add(new WyViewSpot("Huangling", "Huangling is the famous origin of "Sun autumn" culture and an ancient Huizhou village with a history of nearly 600 years; Huangling is a typical mountain village, and the folk houses are arranged in a fan-shaped ladder around the water inlet.")); ag.add(new WyViewSpot("Bifrost", "Rainbow bridge is a distinctive covered bridge in Wuyuan, which is not only beautiful in shape, but also can be used for pedestrians to rest in rainy days. Its name is taken from the Tang poem "two water with a bright mirror, two bridges with a rainbow".")); ag.add(new WyViewSpot("Wolong Valley", "Wolong Valley is national 4 A It is a first-class tourist area, with flying springs and waterfalls discharging silver and jade, colorful pools, secluded pools, green and fresh, tall and straight peaks and rocks, which is a natural splash ink landscape painting.")); it = ag.getIterator(); //Get Wuyuan scenic spot iterator ob = it.first(); this.showPicture(ob.getName(), ob.getIntroduce()); } //display picture void showPicture(String Name, String Introduce) { Container cp = this.getContentPane(); JPanel picturePanel = new JPanel(); JPanel controlPanel = new JPanel(); String FileName = "src/iterator/Picture/" + Name + ".jpg"; JLabel lb = new JLabel(Name, new ImageIcon(FileName), JLabel.CENTER); JTextArea ta = new JTextArea(Introduce); lb.setHorizontalTextPosition(JLabel.CENTER); lb.setVerticalTextPosition(JLabel.TOP); lb.setFont(new Font("Song typeface", Font.BOLD, 20)); ta.setLineWrap(true); ta.setEditable(false); //ta.setBackground(Color.orange); picturePanel.setLayout(new BorderLayout(5, 5)); picturePanel.add("Center", lb); picturePanel.add("South", ta); JButton first, last, next, previous; first = new JButton("First sheet"); next = new JButton("Next"); previous = new JButton("Previous"); last = new JButton("Last sheet"); first.addActionListener(this); next.addActionListener(this); previous.addActionListener(this); last.addActionListener(this); controlPanel.add(first); controlPanel.add(next); controlPanel.add(previous); controlPanel.add(last); cp.add("Center", picturePanel); cp.add("South", controlPanel); this.setSize(630, 550); this.setVisible(true); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } @Override public void actionPerformed(ActionEvent arg0) { String command = arg0.getActionCommand(); if (command.equals("First sheet")) { ob = it.first(); this.showPicture(ob.getName(), ob.getIntroduce()); } else if (command.equals("Next")) { ob = it.next(); this.showPicture(ob.getName(), ob.getIntroduce()); } else if (command.equals("Previous")) { ob = it.previous(); this.showPicture(ob.getName(), ob.getIntroduce()); } else if (command.equals("Last sheet")) { ob = it.last(); this.showPicture(ob.getName(), ob.getIntroduce()); } } } //Wuyuan scenic spots class WyViewSpot { private String Name; private String Introduce; WyViewSpot(String Name, String Introduce) { this.Name = Name; this.Introduce = Introduce; } public String getName() { return Name; } public String getIntroduce() { return Introduce; } } //Abstract aggregation: Wuyuan scenic spot collection interface interface ViewSpotSet { void add(WyViewSpot obj); void remove(WyViewSpot obj); ViewSpotIterator getIterator(); } //Specific aggregation: Wuyuan scenic spot collection class WyViewSpotSet implements ViewSpotSet { private ArrayList<WyViewSpot> list = new ArrayList<WyViewSpot>(); public void add(WyViewSpot obj) { list.add(obj); } public void remove(WyViewSpot obj) { list.remove(obj); } public ViewSpotIterator getIterator() { return (new WyViewSpotIterator(list)); } } //Abstract iterator: Wuyuan scenic spot iterator interface interface ViewSpotIterator { boolean hasNext(); WyViewSpot first(); WyViewSpot next(); WyViewSpot previous(); WyViewSpot last(); } //Specific iterator: Wuyuan scenic spot iterator class WyViewSpotIterator implements ViewSpotIterator { private ArrayList<WyViewSpot> list = null; private int index = -1; WyViewSpot obj = null; public WyViewSpotIterator(ArrayList<WyViewSpot> list) { this.list = list; } public boolean hasNext() { if (index < list.size() - 1) { return true; } else { return false; } } public WyViewSpot first() { index = 0; obj = list.get(index); return obj; } public WyViewSpot next() { if (this.hasNext()) { obj = list.get(++index); } return obj; } public WyViewSpot previous() { if (index > 0) { obj = list.get(--index); } return obj; } public WyViewSpot last() { index = list.size() - 1; obj = list.get(index); return obj; } }
Application scenario of pattern
The structure and characteristics of iterator pattern were introduced earlier, and its application scenarios are introduced below. Iterator pattern is usually used in the following situations.
When you need to provide multiple traversal methods for aggregate objects.
When it is necessary to provide a unified interface for traversing different aggregation structures.
When accessing the contents of an aggregate object without exposing the representation of its internal details.
Because aggregation is closely related to iterators, most languages provide iterators when implementing aggregation classes. Therefore, in most cases, it is enough to use the iterators of existing aggregation classes in the language.