简介

在不扭转原有类的前提下,能够新增不同的拜访器,每种拜访器都可自定义拜访策略。

如超市购物车里什么物品都有,顾客遍历拜访商品次要查看商品是否过期,包装是否残缺,收银员遍历商品次要查看价格。顾客和收银员能够了解为两种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

本文由mdnice多平台公布