学习php设计模式 php实现访问者模式(Visitor)

学习PHP设计模式是我们提高PHP技能的一个必要过程。设计模式是一种通用解决方案,用于解决常见的面向对象编程问题。本文将讲解PHP实现访问者模式的完整攻略,包括对访问者模式的介绍、访问者模式的实现步骤,以及基于PHP实现的两个示例说明。

什么是访问者模式?

访问者模式是一种行为型设计模式,它使得你能够在不改变元素类(被访问的对象)的前提下,定义作用于这些元素的新操作。

换句话说,访问者模式允许你在不改变已有类接口的情况下,定义额外的操作。这是通过将操作从类中移动并将其归结到代表这些操作的单个对象中实现的(访问者)。

当你需要添加新的操作时,只需要实现新的访问者即可。

访问者模式有两个核心角色:

  • 访问者(Visitor):为每个具体类声明一组访问操作。访问者对象使程序员可以向现有的类添加新的操作,而不必修改这些类。
  • 元素(Element):定义一个接受访问者接口(Accept)的操作,其参数是访问者对象。这个操作使访问者对象在访问元素时调用元素的方法。

PHP实现访问者模式

下面是访问者模式的实现步骤。

  1. 定义元素类。元素类定义Accept(接收访问者对象)的操作。这个操作在访问者中被调用。具体实现中,访问者参数应当以参数的形式传递到接受的方法中。

  2. 定义访问者类。访问者类定义所有具体的访问者,这些访问者类实现在特定元素上执行的算法。

  3. 所有访问者类都应该实现同一个Visitor接口。

  4. 为元素类和访问者类之间的关系定义抽象的Visitor接口。

  5. 在访问者类中实现所有要在元素类上执行的操作。

下面是两个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技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • 推荐10个提供免费PHP脚本下载的网站

    以下是推荐10个提供免费PHP脚本下载的网站的完整攻略。 1. 确定搜索关键词 为了找到可靠的并提供免费PHP脚本下载的网站,我们需要在搜索引擎中使用正确的关键词,比如“免费PHP脚本下载”、“PHP脚本库”、“PHP脚本分享”等。 2. 选择可靠的网站 在搜索结果中选择可靠的网站非常重要,因为网上充斥着大量的虚假或低质量的网站,它们可能会提供病毒或恶意软件…

    PHP 2023年5月23日
    00
  • 2014最热门的24个php类库汇总

    首先,为了让读者更容易了解本篇攻略的结构,我们需要为其添加合适的标题,例如: 2014最热门的24个php类库汇总攻略 接下来,我们需要按照常规的markdown语法,编写出详细的攻略内容,包含以下几个方面: 介绍 在攻略的介绍部分,我们需要向读者解释本篇文章的主题和内容,同时也要适当地解释什么是php类库。 一个php类库是一系列PHP类的集合,它们提供了…

    PHP 2023年5月23日
    00
  • PHP中多维数组的foreach遍历示例

    下面是详细的攻略: 什么是多维数组 多维数组是指数组中包含有其他数组的数组,即数组的元素又是一个数组。 例如:$arr = array( array(‘name’=>’张三’, ‘age’=>20), array(‘name’=>’李四’, ‘age’=>22), array(‘name’=>’王五’, ‘age’=>25…

    PHP 2023年5月27日
    00
  • php正则替换变量指定字符的方法

    当我们在使用 PHP 编程时,常常需要对字符串进行正则替换操作。在这个过程中,有时候需要替换字符串中的某个变量的值,而保留其他内容不变。下面是一些关于 PHP 正则表达式替换中指定变量字符的方法。 1. PHP 正则表达式的基本语法 PHP 正则表达式使用特殊的符号来代表字符和字符串的模式。以下是一些常用的符号: ^: 匹配字符串的开头 $:匹配字符串的结尾…

    PHP 2023年5月26日
    00
  • php 输出缓冲 Output Control用法实例详解

    接下来我将详细讲解“PHP 输出缓冲 Output Control 用法实例详解”的完整攻略。 1. 什么是输出缓冲? 在 PHP 中,若开启了输出缓冲(Output Control),则程序在输出到浏览器之前,会把输出先缓存到内存中,待所有 PHP 代码执行完毕后,再一次性把缓存中的内容输出到浏览器。 2. 开启输出缓冲 在 PHP 中,可以通过 ob_s…

    PHP 2023年5月26日
    00
  • PHP实现的DES加密解密类定义与用法示例

    首先我先简单介绍一下DES加密算法。DES加密算法是一种对称性加密算法,采用了数据加密标准(Data Encryption Standard)进行加密和解密。在这个算法中,使用相同的密钥进行加密和解密。 接下来,我将为您详细讲解“PHP实现的DES加密解密类定义与用法示例”的攻略。 操作步骤 步骤一:下载加密解密类文件 我们可以从Github上下载PHP实现…

    PHP 2023年5月26日
    00
  • php cli模式学习(PHP命令行模式)

    以下是关于“PHP CLI模式学习(PHP命令行模式)”的完整攻略。 什么是PHP CLI模式? CLI(Command Line Interface)模式是指在命令行(Windows下的cmd.exe或Linux、macOS下的终端)中运行PHP脚本,而非通过Web服务器(如Apache)来解析脚本。这意味着我们可以在不依赖Web服务器的情况下运行和测试P…

    PHP 2023年5月23日
    00
  • 微信小程序如何获取用户信息

    微信小程序可以通过用户授权方式来获取用户信息,具体步骤如下: 在微信公众平台中,开发者需要设置小程序的“授权选项”,勾选需要获取的用户信息。 在小程序中,调用wx.login()获取用户code,然后使用wx.getUserInfo()方法获取用户信息。 下面是两个示例: 示例一: 打开 app.json 文件,配置一下小程序可以获取到的用户数据。 { &q…

    PHP 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部