1. 设计模式原理说明
迭代器模式(Iterator Pattern) 是一种行为设计模式,它提供了一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。迭代器模式的核心思想是将数据的遍历逻辑与数据结构分离,使得同一个遍历逻辑可以应用于不同的数据结构,同时隐藏了数据结构的内部细节。
主要角色
- Iterator(迭代器):定义了访问和遍历集合元素的接口。
- ConcreteIterator(具体迭代器):实现了 Iterator 接口,负责对集合进行遍历操作。
- Aggregate(聚合):定义了创建 Iterator 对象的接口。
- ConcreteAggregate(具体聚合):实现了在 Aggregate 中声明的创建 Iterator 的方法。
2. UML 类图及解释
UML 类图
+-----------------+
| Iterator |
|-----------------|
| + hasNext(): boolean |
| + next(): Object |
+-----------------+
^
|
|
v
+-----------------+
| ConcreteIterator|
|-----------------|
| - position: int |
| - collection: Collection |
| + hasNext(): boolean |
| + next(): Object |
+-----------------+
+-----------------+
| Aggregate |
|-----------------|
| + createIterator(): Iterator |
+-----------------+
^
|
|
v
+-----------------+
| ConcreteAggregate|
|-----------------|
| - items: List<Object> |
| + createIterator(): Iterator |
+-----------------+
类图解释
- Iterator:定义了访问和遍历集合元素的方法,如
hasNext()
和next()
。 - ConcreteIterator:实现了 Iterator 接口,负责具体的遍历逻辑。它包含一个指向集合的引用和一个表示当前位置的索引。
- Aggregate:定义了创建 Iterator 对象的接口
createIterator()
。 - ConcreteAggregate:实现了 Aggregate 接口中声明的
createIterator()
方法,返回一个具体的迭代器对象。
3. 代码案例及逻辑详解
Java 代码案例
// 迭代器接口
interface Iterator {
boolean hasNext();
Object next();
}
// 具体迭代器
class ConcreteIterator implements Iterator {
private List<Object> list;
private int position = 0;
public ConcreteIterator(List<Object> list) {
this.list = list;
}
@Override
public boolean hasNext() {
return position < list.size();
}
@Override
public Object next() {
if (this.hasNext()) {
Object obj = list.get(position);
position++;
return obj;
}
return null;
}
}
// 聚合接口
interface Aggregate {
Iterator createIterator();
}
// 具体聚合
class ConcreteAggregate implements Aggregate {
private List<Object> list = new ArrayList<>();
public void addItem(Object item) {
list.add(item);
}
@Override
public Iterator createIterator() {
return new ConcreteIterator(list);
}
}
// 客户端
public class Client {
public static void main(String[] args) {
ConcreteAggregate aggregate = new ConcreteAggregate();
aggregate.addItem("Item 1");
aggregate.addItem("Item 2");
aggregate.addItem("Item 3");
Iterator iterator = aggregate.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
C++ 代码案例
#include <iostream>
#include <vector>
#include <memory>
// 迭代器接口
class Iterator {
public:
virtual bool hasNext() const = 0;
virtual std::shared_ptr<void> next() = 0;
virtual ~Iterator() {}
};
// 具体迭代器
class ConcreteIterator : public Iterator {
private:
std::vector<std::shared_ptr<void>> list;
int position = 0;
public:
ConcreteIterator(const std::vector<std::shared_ptr<void>>& list) : list(list) {}
bool hasNext() const override {
return position < list.size();
}
std::shared_ptr<void> next() override {
if (this->hasNext()) {
std::shared_ptr<void> obj = list[position];
position++;
return obj;
}
return nullptr;
}
};
// 聚合接口
class Aggregate {
public:
virtual std::unique_ptr<Iterator> createIterator() const = 0;
virtual ~Aggregate() {}
};
// 具体聚合
class ConcreteAggregate : public Aggregate {
private:
std::vector<std::shared_ptr<void>> list;
public:
void addItem(std::shared_ptr<void> item) {
list.push_back(item);
}
std::unique_ptr<Iterator> createIterator() const override {
return std::make_unique<ConcreteIterator>(list);
}
};
// 客户端
int main() {
ConcreteAggregate aggregate;
aggregate.addItem(std::make_shared<std::string>("Item 1"));
aggregate.addItem(std::make_shared<std::string>("Item 2"));
aggregate.addItem(std::make_shared<std::string>("Item 3"));
auto iterator = aggregate.createIterator();
while (iterator->hasNext()) {
auto item = iterator->next();
if (item) {
std::string* str = static_cast<std::string*>(item.get());
std::cout << *str << std::endl;
}
}
return 0;
}
Python 代码案例
from abc import ABC, abstractmethod
# 迭代器接口
class Iterator(ABC):
@abstractmethod
def has_next(self) -> bool:
pass
@abstractmethod
def next(self) -> object:
pass
# 具体迭代器
class ConcreteIterator(Iterator):
def __init__(self, collection: list):
self.collection = collection
self.position = 0
def has_next(self) -> bool:
return self.position < len(self.collection)
def next(self) -> object:
if self.has_next():
obj = self.collection[self.position]
self.position += 1
return obj
return None
# 聚合接口
class Aggregate(ABC):
@abstractmethod
def create_iterator(self) -> Iterator:
pass
# 具体聚合
class ConcreteAggregate(Aggregate):
def __init__(self):
self.items = []
def add_item(self, item: object):
self.items.append(item)
def create_iterator(self) -> Iterator:
return ConcreteIterator(self.items)
# 客户端
if __name__ == "__main__":
aggregate = ConcreteAggregate()
aggregate.add_item("Item 1")
aggregate.add_item("Item 2")
aggregate.add_item("Item 3")
iterator = aggregate.create_iterator()
while iterator.has_next():
print(iterator.next())
Go 代码案例
package main
import (
"fmt"
)
// 迭代器接口
type Iterator interface {
hasNext() bool
next() interface{}
}
// 具体迭代器
type ConcreteIterator struct {
list []interface{}
position int
}
func (it *ConcreteIterator) hasNext() bool {
return it.position < len(it.list)
}
func (it *ConcreteIterator) next() interface{} {
if it.hasNext() {
obj := it.list[it.position]
it.position++
return obj
}
return nil
}
// 聚合接口
type Aggregate interface {
createIterator() Iterator
}
// 具体聚合
type ConcreteAggregate struct {
items []interface{}
}
func (ag *ConcreteAggregate) addItem(item interface{}) {
ag.items = append(ag.items, item)
}
func (ag *ConcreteAggregate) createIterator() Iterator {
return &ConcreteIterator{list: ag.items}
}
// 客户端
func main() {
aggregate := &ConcreteAggregate{}
aggregate.addItem("Item 1")
aggregate.addItem("Item 2")
aggregate.addItem("Item 3")
iterator := aggregate.createIterator()
for iterator.hasNext() {
fmt.Println(iterator.next())
}
}
4. 总结
迭代器模式 是一种行为设计模式,它提供了一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。通过将数据的遍历逻辑与数据结构分离,迭代器模式使得同一个遍历逻辑可以应用于不同的数据结构,同时隐藏了数据结构的内部细节。
主要优点
- 统一遍历方式:通过迭代器模式,可以为不同的数据结构提供统一的遍历方式,使得客户端代码更加简洁和一致。
- 隐藏内部结构:迭代器模式隐藏了数据结构的内部细节,客户端无需了解数据结构的具体实现即可进行遍历操作。
- 支持多种遍历方式:可以通过实现不同的迭代器来支持多种遍历方式,如正序、逆序等。
主要缺点
- 增加系统复杂性:引入迭代器模式会增加系统的复杂性,特别是对于简单的数据结构,可能显得过于繁琐。
- 性能开销:迭代器模式可能会带来一定的性能开销,尤其是在频繁遍历大量数据时。
适用场景
- 当需要为聚合对象提供多种遍历方式时,可以通过迭代器模式实现。
- 当需要隐藏聚合对象的内部表示,同时又需要提供遍历功能时,可以使用迭代器模式。
- 当聚合对象的遍历逻辑较为复杂,需要将其与聚合对象分离时,可以考虑使用迭代器模式。