robertogallea/laravel-visitor

Laravel的访问者模式实现

1.0.0 2019-09-05 10:48 UTC

This package is auto-updated.

Last update: 2024-09-04 17:50:38 UTC


README

1. 简介

LaravelVisitor是Laravel的一个访问者设计模式实现。它允许轻松地对任意元素的集合执行处理,无需使用重复的条件语句,从而提高代码的抽象性。

没有访问者

public function process() 
{
  $result = '';
  foreach ($this->elements as $element) {
    if ($element instanceof FooClass) {
      $result .= ((FooClass)$element)->getData();
    } elseif ($element instanceof BarClass) {
      $result .= ((BarClass)$element)->getData();
    } elseif ($element instanceof BazClass) {
      $result .= ((BazClass)$element)->getData();
    }
  }
}

有访问者

public function process() 
{
  $visitor = new MyVisitor([
    new FooClass(),
    new BarClass(),
    new BazClass(),
  ]);
  
  $visitor->execute();
  
  $result = $visitor->getResult();
}

所有复杂性都隐藏在必须定义处理类方法的MyVisitor类中。在上面的示例中,MyVisitor将实现如下

class MyVisitor extends Visitor
{
  private $result;
  
  public function getResult()
  {
    return $this->result;
  }
  
  public function visitFooClass(FooClass $fooClass) 
  {
    $this->result .= ... ;
  }
  
  public function visitBarClass(BarClass $fooClass) 
  {
    $this->result .= ... ;
  }
  
  public function visitBazClass(BazClass $fooClass) 
  {
    $this->result .= ... ;
  }
}

此外,这也强制执行了SRP原则,因为领域对象不需要实现表示方法,这些方法仅是访问者类实现的职责(尤其是如果需要多个的话)。

2. 安装

通过composer安装包

composer require robertogallea/laravel-visitor

3. 使用

为了使用此包,您需要定义至少一个Visitor类和一些Visitee类。

3.1. Visitee实现

Visitee的唯一要求是使用Visitable特质,这样您就可以使任何类可访问。

3.2. Visitor实现

Visitor类必须实现CanVisit接口,并继承Visitor抽象类,通过定义getResult()方法。

此外,对于每个定义的Visitee,您都必须实现一个自定义的处理方法。例如,如果您有一个Book Visitee,您必须定义以下方法

public function visitBook(Book $book) {
  ...
}

3.3. Visitor生成

要生成Visitor,您可以运行以下Artisan命令

php artisan make:visitor MyVisitor

该命令默认将类创建在Visitors文件夹中。

4. 示例使用

4.1. Visitee实现

Magazine.php

use robertogallea\LaravelVisitor\Models\Visitable;

class Magazine
{
    use Visitable;

    private $title;
    private $month;
    private $year;

    public function __construct($title, $month, $year)
    {
        $this->title = $title;
        $this->month = $month;
        $this->year = $year;
    }

    public function getTitle()
    {
        return $this->title;
    }

    public function getMonth()
    {
        return $this->month;
    }

    public function getYear()
    {
        return $this->year;
    }

}

4.2. Visitor实现

XMLVisitor.php

use robertogallea\LaravelVisitor\Models\Visitor;

class XMLVisitor extends Visitor
{
    private $xml = '';    

    public function visitMagazine(Magazine $magazine)
    {
        $this->xml .= '<magazine title="' . $magazine->getTitle() . '" ' .
            'issue="' . $magazine->getMonth() . ' ' . $magazine->getYear() . '"></magazine>' . PHP_EOL;
    }

    public function getResult()
    {
        return $this->xml;
    }
}

4.3. 客户端代码

  $xmlCatalog = new XMLVisitor([
    new Magazine('PHP programming', 'July', 2019)
    new Magazine('The art of woodworking', 'August', 2019)
  ]);

  $xmlCatalog->execute();
  
  echo($xmlCatalog->getResult());        

将生成以下输出

<magazine title="PHP programming" issue="July 2019"></magazine>
<magazine title="The art of woodworking" issue="August 2019"></magazine>

5. 问题、问题和拉取请求

您可以在问题部分报告问题并提出问题。请以ISSUE: 开始您的问题,并以QUESTION: 开始您的问题。

如果您有问题,请首先检查已关闭的问题。

要提交拉取请求,请首先从本仓库派生,创建一个新分支,并将您的新/更新代码提交到该分支。然后从您的分支打开拉取请求。有关更多信息,请参阅本指南