PHP设计模式之迭代器模式Iterator实例分析【对象行为型】
迭代器模式是一种经常被使用的行为型设计模式,该模式提供一种简单,有效且通用的解决方案,用于遍历一个聚合对象(例如:列表,集合,数组等),而不需要暴露底层聚合对象的内部表现形式。迭代器模式中,客户端不会与聚合对象交互,而是通过迭代器对象按顺序访问聚合元素。
在PHP应用程序中,迭代器模式非常有用。PHP被广泛应用于Web开发,其中需要访问和操作各种类型的HTML元素,例如表单字段,表格,链接等。这些元素基本上在DOM树结构中表示,并且可以使用迭代器模式(通过DOM迭代器)来访问和操作这些元素。
在下面的示例中,我们将通过使用PHP迭代器模式,实现可以从多个农场中获取动物品种的能力。具体而言,我们有几个农场,其中包含一些动物品种,并且我们需要创建一个迭代器对象,以便能够遍历不同农场中的所有动物品种。
首先,我们需要创建一个接口,用于定义迭代器的行为。在该接口中,我们定义两个方法:
- hasNext():该方法检查迭代器是否到达了列表的末尾,如果没有到达列表末尾,返回true,否则返回false。
- next():该方法获取下一项,并将迭代器内部指针向前移动一个位置。
interface FarmIterator {
public function hasNext(): bool;
public function next(): string;
}
接下来,我们需要创建一个具体的迭代器实现,用于实现FarmIterator接口,并提供迭代器的具体实现细节。在下面的FarmIteratorImpl类中,我们实现FarmIterator接口,并提供以下细节:
- $farms:该属性包含一个Farm对象数组,它将由我们的迭代器遍历。
- $index:该属性表示当前遍历位置。
class FarmIteratorImpl implements FarmIterator {
private $farms;
private $index;
public function __construct(array $farms) {
$this->farms = $farms;
$this->index = 0;
}
public function hasNext(): bool {
return $this->index < count($this->farms);
}
public function next(): string {
if ($this->hasNext()) {
$farm = $this->farms[$this->index];
$this->index += 1;
return $farm->getAnimal();
} else {
return '';
}
}
}
接下来,我们需要创建一个抽象基类,用于定义FarmIterator实例对象的生成方法。在该抽象基类中,我们定义一个抽象方法——createIterator(),该方法接受一个参数(即Farm对象数组),并返回一个FarmIterator实例对象。
abstract class Farm {
public abstract function createIterator(array $farms): FarmIterator;
public abstract function getAnimal(): string;
}
最后,我们需要创建一个具体的Farm实例对象,即SheepFarm和CowFarm,实现Farm抽象类的所有方法。在下面的SheepFarm类中,我们实现了createIterator()和getAnimal()方法。
class SheepFarm extends Farm {
public function createIterator(array $farms): FarmIterator {
return new FarmIteratorImpl($farms);
}
public function getAnimal(): string {
return 'Sheep';
}
}
class CowFarm extends Farm {
public function createIterator(array $farms): FarmIterator {
return new FarmIteratorImpl($farms);
}
public function getAnimal(): string {
return 'Cow';
}
}
现在,我们可以使用上述类的实例对象来遍历多个农场,以获取所有动物品种。在下面的示例中,我们使用了一个FarmManager类,该类接受两个农场的对象,创建迭代器并遍历所有动物品种。
class FarmManager {
public function __construct(Farm $farm1, Farm $farm2) {
$this->farm1 = $farm1;
$this->farm2 = $farm2;
}
public function getAnimalList(): array {
$animalList = [];
$iterator1 = $this->farm1->createIterator([$this->farm1, $this->farm2]);
$iterator2 = $this->farm2->createIterator([$this->farm1, $this->farm2]);
while ($iterator1->hasNext()) {
$animalList[] = $iterator1->next();
}
while ($iterator2->hasNext()) {
$animalList[] = $iterator2->next();
}
return $animalList;
}
}
$farm1 = new SheepFarm();
$farm2 = new CowFarm();
$farmManager = new FarmManager($farm1, $farm2);
foreach ($farmManager->getAnimalList() as $animal) {
echo $animal . '
';
}
在上面的示例中,我们首先创建了一个FarmManager实例对象,并用SheepFarm和CowFarm实例对象初始化它。然后,我们遍历迭代器,将农场中的每种动物添加到$animalList数组中,并在遍历结束后将该数组作为结果返回。
在客户端代码中,我们仅使用FarmManager和Farm抽象类,不需要了解农场对象数组或迭代器实现的细节。这使得代码更易维护和扩展,并将迭代器实现细节隐藏在内部。
