写点什么

行为型设计模式 - 访问器 Visitor

作者:菜皮日记
  • 2023-09-08
    北京
  • 本文字数:1721 字

    阅读完需:约 6 分钟

简介

在不改变原有类的前提下,可以新增不同的访问器,每种访问器都可自定义访问策略。

如超市购物车里什么物品都有,顾客遍历访问商品主要查看商品是否过期,包装是否完整,收银员遍历商品主要查看价格。顾客和收银员可以理解为两种 Visitor,各自关注的重点就是 Visitor 中的 visit 方法实现逻辑。

原始数据结构就像数据库,而访问器就像基于该数据库的业务逻辑,不同访问器按照不同业务规则使用数据。

角色

  • 抽象 Visitor

    定义访问每一种 Element 的方法签名 visit

  • 具体 Visitor

    实现具体访问方法 visit

  • 抽象 Element

    定义 accept 方法,支持将 visitor 做参数,通过调用 accept 方法,实现 accept→visitor→visit 的调用

  • 具体 Element

    实现具体方法

类图

如图,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 + ConcreteVisitor1B + ConcreteVisitor1It allows the same client code to work with different types of visitors:A + ConcreteVisitor2B + ConcreteVisitor2
复制代码


用户头像

菜皮日记

关注

全干程序员 2018-08-08 加入

还未添加个人简介

评论

发布
暂无评论
行为型设计模式-访问器 Visitor_设计模式_菜皮日记_InfoQ写作社区