乐趣区

关于后端:行为型设计模式访问器-Visitor

简介

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

如超市购物车里什么物品都有,顾客遍历拜访商品次要查看商品是否过期,包装是否残缺,收银员遍历商品次要查看价格。顾客和收银员能够了解为两种 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 + ConcreteVisitor1
B + ConcreteVisitor1
It allows the same client code to work with different types of visitors:
A + ConcreteVisitor2
B + ConcreteVisitor2

本文由 mdnice 多平台公布

退出移动版