Design pattern (10) - iterative mode

Iterator (Iterator) mode provides a sequential method for each element in a polymeric object, without showing the inside thereof is exposed.

If you have a uniform method of accessing the polymerization of each object, you can write polymorphic code and these polymerization with use. Iterative mode between the elements of the responsibility to the migration of iterators, instead of aggregate objects. This not only allows aggregation of interface and implementation become more concise, but also allows polymerization to focus more on things above, we should focus on (that is, a collection of managed objects) without having to traverse to ignore things.

Below with reference to a specific example will be described.

We simulated a restaurant, a pancake house and a cafe, now we want to let customers in the same place at the same time be able to point the dish three restaurants.

In the original menu implementation, the restaurant's menu with 数组recorded menu items, pancake house menu with ArrayListrecorded menu items, while the café with a menu Hashtableto record menu item.

We extracted the menu interface

import java.util.Iterator;

public interface Menu {
	public Iterator createIterator();
}

Class menu item is

public class MenuItem {
	String name;
	String description;
	boolean vegetarian;
	double price;
 
	public MenuItem(String name, 
	                String description, 
	                boolean vegetarian, 
	                double price) 
	{
		this.name = name;
		this.description = description;
		this.vegetarian = vegetarian;
		this.price = price;
	}
  
	public String getName() {
		return name;
	}
  
	public String getDescription() {
		return description;
	}
  
	public double getPrice() {
		return price;
	}
  
	public boolean isVegetarian() {
		return vegetarian;
	}
}

We need to create a Java version of the waitress, she needs to be able to respond to the customer's need to print custom menus, and even tell you whether a menu item is vegetarian, without having to ask the chef.

We need to find a way to let these restaurant menus achieve a same interface. In the previous article mentioned, we have an important design principle is part of the package of changes . Clearly, changes here are traversed by a set of different types caused. We need the help of the iterator pattern to solve this problem.

Iterative mode relies on an interface called iterator

public interface Iterator {
	boolean hasNext();
	Object next();
}

For the pancake house ArrayListmenu and cafe Hashtablemenu, Java have achieved its default iterator, and for the restaurant's 数组menu, you need to realize that we own an iterator:

import java.util.Iterator;
  
public class DinerMenuIterator implements Iterator {
	MenuItem[] list;
	int position = 0;
 
	public DinerMenuIterator(MenuItem[] list) {
		this.list = list;
	}
 
	public Object next() {
		MenuItem menuItem = list[position];
		position = position + 1;
		return menuItem;
	}
 
	public boolean hasNext() {
		if (position >= list.length || list[position] == null) {
			return false;
		} else {
			return true;
		}
	}
  
	public void remove() {
		if (position <= 0) {
			throw new IllegalStateException
				("You can't remove an item until you've done at least one next()");
		}
		if (list[position-1] != null) {
			for (int i = position-1; i < (list.length-1); i++) {
				list[i] = list[i+1];
			}
			list[list.length-1] = null;
		}
	}
}

The corresponding implemented as restaurant menus

import java.util.Iterator;

public class DinerMenu implements Menu {
	static final int MAX_ITEMS = 6;
	int numberOfItems = 0;
	MenuItem[] menuItems;
  
	public DinerMenu() {
		menuItems = new MenuItem[MAX_ITEMS];
 
		addItem("Vegetarian BLT",
			"(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99);
		addItem("BLT",
			"Bacon with lettuce & tomato on whole wheat", false, 2.99);
		addItem("Soup of the day",
			"Soup of the day, with a side of potato salad", false, 3.29);
		addItem("Hotdog",
			"A hot dog, with saurkraut, relish, onions, topped with cheese",
			false, 3.05);
		addItem("Steamed Veggies and Brown Rice",
			"A medly of steamed vegetables over brown rice", true, 3.99);
		addItem("Pasta",
			"Spaghetti with Marinara Sauce, and a slice of sourdough bread",
			true, 3.89);
	}
  
	public void addItem(String name, String description, 
	                     boolean vegetarian, double price) 
	{
		MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
		if (numberOfItems >= MAX_ITEMS) {
			System.err.println("Sorry, menu is full! Can't add item to menu");
		} else {
			menuItems[numberOfItems] = menuItem;
			numberOfItems = numberOfItems + 1;
		}
	}
 
	public MenuItem[] getMenuItems() {
		return menuItems;
	}
  
	public Iterator createIterator() {
		return new DinerMenuIterator(menuItems);
		//return new AlternatingDinerMenuIterator(menuItems);
	}
 
	// other menu methods here
}

Design principles - Single Responsibility Principle

If we allow us to achieve the set of polymerization inside them, as well as related operations and methods to traverse, so that we not only allows a class to complete their own thing (kind of a polymerization), also at the same time to bear more responsibility (eg traversal), we gave two reasons for this kind of change:

  • If this collection changes, then this class must change with it
  • If we traverse the way of change, this category also must change with it

So, our old friend "change", has once again become the center of our design principles - the single responsibility principle: a class should be only one reason for any changes.

Published 295 original articles · won praise 37 · views 30000 +

Guess you like

Origin blog.csdn.net/tianshan2010/article/details/104714034