[toc]
## 举个例子
> **去医院排队看病**
1. 您前面还有n位病友...
1. 请××号患者×××去第×诊室就诊...
1. 请××号患者××做准备...
## 代码示例
```php
<?php
// 病人
class Customer {
private $name;
private $num;
private $clinics;
public function __construct($name) {
$this->name = $name;
$this->num = 0;
$this->clinics = null;
}
public function getName() {
return $this->name;
}
public function register($system) {
$system->pushCustomer($this);
}
public function setNum($num) {
$this->num = $num;
}
public function getNum() {
return $this->num;
}
public function setClinic($clinic) {
$this->clinics = $clinic;
}
public function getClinic() {
return $this->clinics;
}
}
// 迭代器
class PHPIterator {
private $data;
private $curIdx;
public function __construct($data) {
$this->data = $data;
$this->curIdx = -1;
}
public function current() {
if (count($this->data) >= $this->curIdx) {
return $this->data[$this->curIdx];
}
}
public function next() {
if ($this->curIdx < count($this->data) - 1) {
$this->curIdx += 1;
return true;
}
}
}
// 排号系统
class NumeralSystem {
private $clinics = ["1号分诊室", "2号分诊室", "3号分诊室"];
private $customers;
private $curNum;
private $name;
public function __construct($name) {
$this->customers = [];
$this->curNum = 0;
$this->name = $name;
}
public function pushCustomer($customer) {
$customer->setNum($this->curNum + 1);
$click = $this->clinics[$this->curNum % count($this->clinics)];
$customer->setClinic($click);
$this->curNum += 1;
array_push($this->customers, $customer);
echo $customer->getName() . "您好!您已在" . $this->name . "成功挂号,序号:" . str_pad($customer->getNum(), 4, '0') . ",请耐心等待!" . PHP_EOL;
}
public function getIterator() {
return new PHPIterator($this->customers);
}
}
// 测试
$numeralSystem = new NumeralSystem("挂号台");
$lily = new Customer("Lily");
$lily->register($numeralSystem);
$pony = new Customer("Pony");
$pony->register($numeralSystem);
$nick = new Customer("Nick");
$nick->register($numeralSystem);
$tony = new Customer("Tony");
$tony->register($numeralSystem);
$iterator = $numeralSystem->getIterator();
while ($iterator->next()) {
$customer = $iterator->current();
echo "下一位病人" . str_pad($customer->getNum(), 4, '0') . $customer->getName() . " 请到" . $customer->getClinic() . "就诊。" . PHP_EOL;
}
```
```
D:\soft\php72\php.exe D:\project\php_dp\index.php
Lily您好!您已在挂号台成功挂号,序号:1000,请耐心等待!
Pony您好!您已在挂号台成功挂号,序号:2000,请耐心等待!
Nick您好!您已在挂号台成功挂号,序号:3000,请耐心等待!
Tony您好!您已在挂号台成功挂号,序号:4000,请耐心等待!
下一位病人1000Lily 请到1号分诊室就诊。
下一位病人2000Pony 请到2号分诊室就诊。
下一位病人3000Nick 请到3号分诊室就诊。
下一位病人4000Tony 请到1号分诊室就诊。
Process finished with exit code 0
```
## 代码说明
> 医院的排号系统就像是病人队伍的大管家,通过数字化的方式精确地维护着先来先就诊的秩序。
> 医生不用在乎外面有多少人在等待,更不需要了解每一个人的名字和具体信息。
> 他只要在诊断完一个病人后按一下按钮,排号系统就会自动为他呼叫下一位病人,这样医生就可只专注于病情的诊断!
![](https://box.kancloud.cn/1210aaf6956417feea34b8a593285100_741x283.png)
## 什么是迭代模式?
> 提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。
> 迭代器(Iterator)是按照一定的顺序对一个或多个容器中的元素从前往遍历的一种机制,比如 for 循环就是一种最简单的迭代器,对一个数组的遍历也是一种迭代遍历的过程。
## 优缺点
**迭代器模式的优点**
1. 迭代器模式将存储数据和遍历数据的职责分离。
2. 简化了聚合数据的访问方式。
3. 可支持多种不同的方式(如顺序和逆序)遍历一个聚合对象。
**迭代器模式的缺点**
1. 需要额外增加迭代器的功能实现,增加新的聚合类时,可能需要增加新的迭代器。
## 应用场景
1. 集合的内部结构复杂,不想暴露对象的内部细节,只提供精简的访问方式。
1. 需要提供统一的访问接口,从而对不同的集合使用同一的算法。
1. 需要为一系列聚合对象提供多种不同的访问方式。