迭代器与组合模式:遍历与管理的艺术
在《Head First 设计模式》中,**迭代器模式(Iterator Pattern)和组合模式(Composite Pattern)**是两个非常重要的设计模式。迭代器模式帮助我们遍历集合中的元素,而组合模式则帮助我们管理树形结构的对象。这两种模式在实际开发中有着广泛的应用,尤其是在JDK和Spring等框架中。今天,我们将通过书中的内容,结合代码示例,来深入理解这两种模式。
迭代器模式:遍历集合的艺术
迭代器模式的定义是:
提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
简单来说,迭代器模式将遍历集合的责任从集合类中分离出来,交给一个独立的迭代器对象。这样,集合类可以专注于管理元素,而迭代器类可以专注于遍历元素。
迭代器模式的核心思想
- 分离遍历与集合:将遍历集合的逻辑从集合类中分离出来,交给迭代器类。
- 统一的遍历接口:通过统一的接口(如
Iterator
),可以遍历不同类型的集合。
代码示例:迭代器模式
我们通过一个简单的例子来理解迭代器模式。假设我们有一个菜单系统,包含两个菜单:PancakeHouseMenu
和 DinerMenu
。我们希望遍历这两个菜单中的所有菜品。
定义菜单项
class MenuItem {
String name;
double price;
MenuItem(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
定义菜单
import java.util.ArrayList;
import java.util.List;
class PancakeHouseMenu {
private List<MenuItem> menuItems;
PancakeHouseMenu() {
menuItems = new ArrayList<>();
addItem("K&B's Pancake Breakfast", 2.99);
addItem("Regular Pancake Breakfast", 2.99);
addItem("Blueberry Pancakes", 3.49);
}
void addItem(String name, double price) {
menuItems.add(new MenuItem(name, price));
}
Iterator<MenuItem> createIterator() {
return menuItems.iterator();
}
}
class DinerMenu {
private static final int MAX_ITEMS = 6;
private int numberOfItems = 0;
private MenuItem[] menuItems;
DinerMenu() {
menuItems = new MenuItem[MAX_ITEMS];
addItem("Vegetarian BLT", 2.99);
addItem("BLT", 2.99);
addItem("Soup of the day", 3.29);
}
void addItem(String name, double price) {
if (numberOfItems >= MAX_ITEMS) {
System.out.println("Sorry, menu is full!");
} else {
menuItems[numberOfItems] = new MenuItem(name, price);
numberOfItems++;
}
}
Iterator<MenuItem> createIterator() {
return new DinerMenuIterator(menuItems);
}
}
定义迭代器
import java.util.Iterator;
class DinerMenuIterator implements Iterator<MenuItem> {
private MenuItem[] items;
private int position = 0;
DinerMenuIterator(MenuItem[] items) {
this.items = items;
}
@Override
public boolean hasNext() {
return position < items.length && items[position] != null;
}
@Override
public MenuItem next() {
MenuItem menuItem = items[position];
position++;
return menuItem;
}
}
测试代码
public class MenuTest {
public static void main(String[] args) {
PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
DinerMenu dinerMenu = new DinerMenu();
Iterator<MenuItem> pancakeIterator = pancakeHouseMenu.createIterator();
Iterator<MenuItem> dinerIterator = dinerMenu.createIterator();
System.out.println("MENU\n----\nBREAKFAST");
printMenu(pancakeIterator);
System.out.println("\nLUNCH");
printMenu(dinerIterator);
}
private static void printMenu(Iterator<MenuItem> iterator) {
while (iterator.hasNext()) {
MenuItem menuItem = iterator.next();
System.out.println(menuItem.getName() + ", " + menuItem.getPrice());
}
}
}
输出结果:
MENU
----
BREAKFAST
K&B's Pancake Breakfast, 2.99
Regular Pancake Breakfast, 2.99
Blueberry Pancakes, 3.49
LUNCH
Vegetarian BLT, 2.99
BLT, 2.99
Soup of the day, 3.29
组合模式:管理树形结构的艺术
组合模式的定义是:
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
简单来说,组合模式允许我们将对象组合成树形结构,并且可以像处理单个对象一样处理整个树形结构。
组合模式的核心思想
- 统一叶子节点和组合节点:叶子节点和组合节点实现相同的接口,用户可以一致地处理它们。
- 递归结构:组合节点可以包含其他组合节点或叶子节点,形成递归结构。
代码示例:组合模式
我们通过一个简单的例子来理解组合模式。假设我们有一个菜单系统,菜单可以包含子菜单和菜单项。
定义组件接口
interface MenuComponent {
void print();
}
定义叶子节点(菜单项)
class MenuItem implements MenuComponent {
private String name;
private double price;
MenuItem(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public void print() {
System.out.println(name + ", " + price);
}
}
定义组合节点(菜单)
import java.util.ArrayList;
import java.util.List;
class Menu implements MenuComponent {
private String name;
private List<MenuComponent> menuComponents = new ArrayList<>();
Menu(String name) {
this.name = name;
}
void add(MenuComponent menuComponent) {
menuComponents.add(menuComponent);
}
@Override
public void print() {
System.out.println("\n" + name);
System.out.println("---------------------");
for (MenuComponent menuComponent : menuComponents) {
menuComponent.print();
}
}
}
测试代码
public class MenuTest {
public static void main(String[] args) {
MenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU");
pancakeHouseMenu.add(new MenuItem("K&B's Pancake Breakfast", 2.99));
pancakeHouseMenu.add(new MenuItem("Regular Pancake Breakfast", 2.99));
MenuComponent dinerMenu = new Menu("DINER MENU");
dinerMenu.add(new MenuItem("Vegetarian BLT", 2.99));
dinerMenu.add(new MenuItem("BLT", 2.99));
MenuComponent allMenus = new Menu("ALL MENUS");
allMenus.add(pancakeHouseMenu);
allMenus.add(dinerMenu);
allMenus.print();
}
}
输出结果:
ALL MENUS
---------------------
PANCAKE HOUSE MENU
---------------------
K&B's Pancake Breakfast, 2.99
Regular Pancake Breakfast, 2.99
DINER MENU
---------------------
Vegetarian BLT, 2.99
BLT, 2.99
迭代器与组合模式在JDK和Spring中的应用
1. JDK中的迭代器模式
JDK中的 java.util.Iterator
接口是迭代器模式的典型实现。例如,ArrayList
和 HashSet
都提供了 iterator()
方法,用于返回一个迭代器对象。
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
2. Spring中的组合模式
Spring框架中的 org.springframework.core.io.Resource
接口是组合模式的典型实现。Resource
接口既可以表示单个资源(如文件),也可以表示多个资源(如目录)。
Resource resource = new FileSystemResource("file.txt");
System.out.println(resource.getFilename());
总结
迭代器模式和组合模式是两个非常重要的设计模式。迭代器模式帮助我们遍历集合中的元素,而组合模式则帮助我们管理树形结构的对象。这两种模式在实际开发中有着广泛的应用,尤其是在JDK和Spring等框架中。
通过《Head First 设计模式》中的内容,我们深入理解了这两种模式的核心思想,并通过代码示例掌握了它们的实际应用。希望这篇文章能帮助你更好地理解迭代器模式和组合模式,并在实际开发中灵活运用它们!
互动话题:你在实际开发中使用过迭代器模式或组合模式吗?欢迎在评论区分享你的经验和心得!