[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
```
## 代碼說明
> 醫院的排號系統就像是病人隊伍的大管家,通過數字化的方式精確地維護著先來先就診的秩序。
> 醫生不用在乎外面有多少人在等待,更不需要了解每一個人的名字和具體信息。
> 他只要在診斷完一個病人后按一下按鈕,排號系統就會自動為他呼叫下一位病人,這樣醫生就可只專注于病情的診斷!

## 什么是迭代模式?
> 提供一種方法訪問一個容器(container)對象中各個元素,而又不需暴露該對象的內部細節。
> 迭代器(Iterator)是按照一定的順序對一個或多個容器中的元素從前往遍歷的一種機制,比如 for 循環就是一種最簡單的迭代器,對一個數組的遍歷也是一種迭代遍歷的過程。
## 優缺點
**迭代器模式的優點**
1. 迭代器模式將存儲數據和遍歷數據的職責分離。
2. 簡化了聚合數據的訪問方式。
3. 可支持多種不同的方式(如順序和逆序)遍歷一個聚合對象。
**迭代器模式的缺點**
1. 需要額外增加迭代器的功能實現,增加新的聚合類時,可能需要增加新的迭代器。
## 應用場景
1. 集合的內部結構復雜,不想暴露對象的內部細節,只提供精簡的訪問方式。
1. 需要提供統一的訪問接口,從而對不同的集合使用同一的算法。
1. 需要為一系列聚合對象提供多種不同的訪問方式。