学习PHP设计模式是我们提高PHP技能的一个必要过程。设计模式是一种通用解决方案,用于解决常见的面向对象编程问题。本文将讲解PHP实现访问者模式的完整攻略,包括对访问者模式的介绍、访问者模式的实现步骤,以及基于PHP实现的两个示例说明。
什么是访问者模式?
访问者模式是一种行为型设计模式,它使得你能够在不改变元素类(被访问的对象)的前提下,定义作用于这些元素的新操作。
换句话说,访问者模式允许你在不改变已有类接口的情况下,定义额外的操作。这是通过将操作从类中移动并将其归结到代表这些操作的单个对象中实现的(访问者)。
当你需要添加新的操作时,只需要实现新的访问者即可。
访问者模式有两个核心角色:
- 访问者(Visitor):为每个具体类声明一组访问操作。访问者对象使程序员可以向现有的类添加新的操作,而不必修改这些类。
- 元素(Element):定义一个接受访问者接口(Accept)的操作,其参数是访问者对象。这个操作使访问者对象在访问元素时调用元素的方法。
PHP实现访问者模式
下面是访问者模式的实现步骤。
-
定义元素类。元素类定义Accept(接收访问者对象)的操作。这个操作在访问者中被调用。具体实现中,访问者参数应当以参数的形式传递到接受的方法中。
-
定义访问者类。访问者类定义所有具体的访问者,这些访问者类实现在特定元素上执行的算法。
-
所有访问者类都应该实现同一个Visitor接口。
-
为元素类和访问者类之间的关系定义抽象的Visitor接口。
-
在访问者类中实现所有要在元素类上执行的操作。
下面是两个PHP示例,展示了如何以访问者模式实现一个画图应用程序。
示例1:
<?php
interface Visitor {
public function visitDot(Dot $dot);
public function visitCircle(Circle $circle);
public function visitRectangle(Rectangle $rect);
}
interface Element {
public function accept(Visitor $visitor);
}
class Dot implements Element {
public $name;
public $x;
public $y;
public function __construct(string $name, int $x, int $y) {
$this->name = $name;
$this->x = $x;
$this->y = $y;
}
public function accept(Visitor $visitor) {
$visitor->visitDot($this);
}
}
class Circle implements Element {
public $name;
public $x;
public $y;
public $radius;
public function __construct(string $name, int $x, int $y, int $radius) {
$this->name = $name;
$this->x = $x;
$this->y = $y;
$this->radius = $radius;
}
public function accept(Visitor $visitor) {
$visitor->visitCircle($this);
}
}
class Rectangle implements Element {
public $name;
public $x1;
public $y1;
public $x2;
public $y2;
public function __construct(string $name, int $x1, int $y1, int $x2, int $y2) {
$this->name = $name;
$this->x1 = $x1;
$this->y1 = $y1;
$this->x2 = $x2;
$this->y2 = $y2;
}
public function accept(Visitor $visitor) {
$visitor->visitRectangle($this);
}
}
class XMLExportVisitor implements Visitor {
public function visitDot(Dot $dot) {
echo '<dot x="' . $dot->x . '" y="' . $dot->y . '" name="' . $dot->name . '"/>' . PHP_EOL;
}
public function visitCircle(Circle $circle) {
echo '<circle x="' . $circle->x . '" y="' . $circle->y . '" radius="' . $circle->radius . '" name="' . $circle->name . '"/>' . PHP_EOL;
}
public function visitRectangle(Rectangle $rect) {
echo '<rect x1="' . $rect->x1 . '" y1="' . $rect->y1 . '" x2="' . $rect->x2 . '" y2="' . $rect->y2 . '" name="' . $rect->name . '"/>' . PHP_EOL;
}
}
$drawing = [
new Dot('Dot 1', 10, 20),
new Circle('Circle 1', 20, 30, 5),
new Rectangle('Rectangle 1', 10, 10, 20, 20)
];
$xmlExport = new XMLExportVisitor();
foreach ($drawing as $shape) {
$shape->accept($xmlExport);
}
这个示例中展示了一个画图应用,它可以显示点、圆和矩形。这个应用中有一个XMLExportVisitor类,它能够将画图中的所有元素导出为XML格式。
示例2:
<?php
interface Visitor {
public function visit(Soldier $soldier);
public function visit(Lieutenant $lieutenant);
public function visit(Commander $commander);
}
interface Unit {
public function accept(Visitor $visitor);
}
class Commander implements Unit {
private $name;
private $unit = array();
public function __construct($name) {
$this->name = $name;
}
public function addUnit(Unit $unit) {
$this->unit[] = $unit;
}
public function accept(Visitor $visitor) {
$visitor->visit($this);
foreach ($this->unit as $thisUnit) {
$thisUnit->accept($visitor);
}
}
}
class Lieutenant implements Unit {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function accept(Visitor $visitor) {
$visitor->visit($this);
}
}
class Soldier implements Unit {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function accept(Visitor $visitor) {
$visitor->visit($this);
}
}
class UnitCounterVisitor implements Visitor {
private $soldiers = 0;
private $lieutenants = 0;
private $commanders = 0;
public function visit(Soldier $soldier) {
$this->soldiers++;
}
public function visit(Lieutenant $lieutenant) {
$this->lieutenants++;
}
public function visit(Commander $commander) {
$this->commanders++;
}
public function getCounts() {
return array('soldiers' => $this->soldiers, 'lieutenants' => $this->lieutenants, 'commanders' => $this->commanders);
}
}
$army = new Commander('Commander');
$army->addUnit(new Lieutenant('Lieutenant 1'));
$army->addUnit(new Lieutenant('Lieutenant 2'));
$armyA = new Commander('Commander A');
$armyA->addUnit(new Soldier('Soldier 1'));
$armyA->addUnit(new Soldier('Soldier 2'));
$armyA->addUnit(new Soldier('Soldier 3'));
$armyB = new Commander('Commander B');
$armyB->addUnit(new Lieutenant('Lieutenant 3'));
$army->addUnit($armyA);
$army->addUnit($armyB);
$counter = new UnitCounterVisitor();
$army->accept($counter);
print_r($counter->getCounts());
这个示例中展示了一个军队,包括了士兵、中尉和指挥官。这个示例计算了军队中的士兵、中尉和指挥官的数量。
结论
访问者模式让我们可以通过访问者的方式,对不同的对象进行自定义操作,而不必修改它们的源代码。这种方式可以方便我们扩展和维护代码。通过本文的介绍,读者应该对访问者模式在PHP中的实现以及如何应用访问者模式来创建一个多态的应用程序有更加深刻的认识。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:学习php设计模式 php实现访问者模式(Visitor) - Python技术站