简介
在不改变原有类的前提下,可以新增不同的访问器,每种访问器都可自定义访问策略。
如超市购物车里什么物品都有,顾客遍历访问商品主要查看商品是否过期,包装是否完整,收银员遍历商品主要查看价格。顾客和收银员可以理解为两种 Visitor,各自关注的重点就是 Visitor 中的 visit 方法实现逻辑。
原始数据结构就像数据库,而访问器就像基于该数据库的业务逻辑,不同访问器按照不同业务规则使用数据。
角色
类图
如图,Element 中的 accept 方法以 Visitor 做参数,其中调用 visitor.visit 方法,将主动权交给 Visitor 去处理。实现每新增一种 visitor,对原 Element 无感知
类图
代码
interface Component
{
public function accept(Visitor $visitor): void;
}
class ConcreteComponentA implements Component
{
public function accept(Visitor $visitor): void
{
$visitor->visitConcreteComponentA($this);
}
public function exclusiveMethodOfConcreteComponentA(): string
{
return "A";
}
}
class ConcreteComponentB implements Component
{
public function accept(Visitor $visitor): void
{
$visitor->visitConcreteComponentB($this);
}
public function specialMethodOfConcreteComponentB(): string
{
return "B";
}
}
interface Visitor
{
public function visitConcreteComponentA(ConcreteComponentA $element): void;
public function visitConcreteComponentB(ConcreteComponentB $element): void;
}
class ConcreteVisitor1 implements Visitor
{
public function visitConcreteComponentA(ConcreteComponentA $element): void
{
echo $element->exclusiveMethodOfConcreteComponentA() . " + ConcreteVisitor1\n";
}
public function visitConcreteComponentB(ConcreteComponentB $element): void
{
echo $element->specialMethodOfConcreteComponentB() . " + ConcreteVisitor1\n";
}
}
class ConcreteVisitor2 implements Visitor
{
public function visitConcreteComponentA(ConcreteComponentA $element): void
{
echo $element->exclusiveMethodOfConcreteComponentA() . " + ConcreteVisitor2\n";
}
public function visitConcreteComponentB(ConcreteComponentB $element): void
{
echo $element->specialMethodOfConcreteComponentB() . " + ConcreteVisitor2\n";
}
}
function clientCode(array $components, Visitor $visitor)
{
foreach ($components as $component) {
$component->accept($visitor);
}
}
$components = [
new ConcreteComponentA(),
new ConcreteComponentB(),
];
echo "The client code works with all visitors via the base Visitor interface:\n";
$visitor1 = new ConcreteVisitor1();
clientCode($components, $visitor1);
echo "It allows the same client code to work with different types of visitors:\n";
$visitor2 = new ConcreteVisitor2();
clientCode($components, $visitor2);
复制代码
output:
The client code works with all visitors via the base Visitor interface:
A + ConcreteVisitor1
B + ConcreteVisitor1
It allows the same client code to work with different types of visitors:
A + ConcreteVisitor2
B + ConcreteVisitor2
复制代码
评论