访问者模式允许将对象上的操作外包给其他对象。这样做的主要原因是保持关注数据结构和数据操作的分离。但是类必须定义一个允许访问的契约(示例中的Role::accept方法)。
契约是一个抽象类,但你也可以就是一个接口。在这种情况下,每个Visitor必须自己选择要调用哪个方法。
RoleVisitor.php
<?php declare(strict_types=1); namespace DesignPatternsBehavioralVisitor; interface RoleVisitor { public function visitUser(User $role); public function visitGroup(Group $role); }
RecordingVisitor.php
<?php declare(strict_types=1); namespace DesignPatternsBehavioralVisitor; class RecordingVisitor implements RoleVisitor { private array $visited = []; public function visitGroup(Group $role) { $this->visited[] = $role; } public function visitUser(User $role) { $this->visited[] = $role; } public function getVisited(): array { return $this->visited; } }
Role.php
<?php declare(strict_types=1); namespace DesignPatternsBehavioralVisitor; interface Role { public function accept(RoleVisitor $visitor); }
User.php
<?php declare(strict_types=1); namespace DesignPatternsBehavioralVisitor; class User implements Role { public function __construct(private string $name) { } public function getName(): string { return sprintf("User %s", $this->name); } public function accept(RoleVisitor $visitor) { $visitor->visitUser($this); } }
Group.php
<?php declare(strict_types=1); namespace DesignPatternsBehavioralVisitor; class Group implements Role { public function __construct(private string $name) { } public function getName(): string { return sprintf("Group: %s", $this->name); } public function accept(RoleVisitor $visitor) { $visitor->visitGroup($this); } }
Tests/VisitorTest.php
<?php declare(strict_types=1); namespace DesignPatternsTestsVisitorTests; use DesignPatternsBehavioralVisitorRecordingVisitor; use DesignPatternsBehavioralVisitorUser; use DesignPatternsBehavioralVisitorGroup; use DesignPatternsBehavioralVisitorRole; use DesignPatternsBehavioralVisitor; use PHPUnitFrameworkTestCase; class VisitorTest extends TestCase { private RecordingVisitor $visitor; protected function setUp(): void { $this->visitor = new RecordingVisitor(); } public function provideRoles() { return [ [new User("Dominik")], [new Group("Administrators")], ]; } public function testVisitSomeRole(Role $role) { $role->accept($this->visitor); $this->assertSame($role, $this->visitor->getVisited()[0]); } }
对于某些类型的结果集,结果集支持 refreshRow 方法来重新获取数据,包括返回数据库以重新获取与结果集中的 n 行相对应的数据库...
出现错误信息 “Could not read resultset: unexpected end of stream, read 0 bytes from 4”这是在与服务器通信时出现的问题。...
本节主要介绍如何使用 Oracle XA 功能实现分布式事务的示例。Oracle XA 导入使用 Oracle XA 功能必须导入以下内容:import oracl...
在Impala中,数据库是一种在其命名空间中保存相关表,视图和函数的构造。 它在HDFS中表示为目录树; 它包含表分区和数据文件。 本...
Impala的Truncate Table语句用于从现有表中删除所有记录。 您也可以使用DROP TABLE命令删除一个完整的表,但它会从数据库中...
一般来说,select查询的resultset中的行从0开始。使用offset子句,我们可以决定从哪里考虑输出。 例如,如果我们选择偏移为...
场景介绍TTS、Wireless、Network、Input、Sound、Display、Date、Call、General 九类定义了表征终端设备状态的相关字段,如屏幕...