首页后端开发JAVAphp设计模式(二十四):访问者模式(Visitor)

php设计模式(二十四):访问者模式(Visitor)

时间2023-10-21 14:40:03发布访客分类JAVA浏览740
导读:访问者模式访问者模式又称为:Visitor。访问者模式是一种行为设计模式,它能将算法与其所作用的对象隔离开来。访问者模式表示一个作用于某对象结构中各元素的操作。它可以在不修改各元素类的前提下定义作用于这些元素的新操作,即动态的增加具体访问者...

访问者模式

访问者模式又称为:Visitor。访问者模式是一种行为设计模式,它能将算法与其所作用的对象隔离开来

访问者模式表示一个作用于某对象结构中各元素的操作。它可以在不修改各元素类的前提下定义作用于这些元素的新操作,即动态的增加具体访问者角色

也就是说访问者模式是适用于 稳定的结构什么是稳定的结构呢? 稳定结构是指我们的对象在早之前已经开发好了,功能都实现好了(前面版本)。访问者模式是说现在我们突然要给这个开发好的结构(稳定结构),在不影响原来稳定的基础上,增添一些职责或者功能,所以说访问者模式是马后炮行为。

访问者模式是利用了双重分派。先将访问者传入元素对象的 Accept 方法中,然后元素对象再将自己传入访问者,之后访问者执行元素的相应方法。

问题

假设我们已经编写好一个操作(打开、关闭、或者内容) Pdf、Word、Xml 文件代码,现在突然我们顶头上司,需要我们实现将这些文件里的文字内容导出到 Txt 文件中。

我们可能会对每个文件对象中都写一个将内容导出 Txt 文件的方法。

过了几天顶头上司又要我们写一个将这些文件内容导出成 图片 可视化格式(类似截图内容),我们又在每个文件对象中都写一个将内容导出 图片 文件的方法。

问题是我们后面可能顶头上司会让我们支持导出其他更多的格式,我们如果这么一个个写的对象类中,会使代码越来越复杂且臃肿,且不说我们新增导出各种格式不会影响这个类原有功能的使用,可能到后面代码多起来我们自己都看不懂?所以我们应该怎么解决呢?

解决方法

我们可以使用访问器模式,给 Pdf、Word、Xml 文件代码提供一个访问者,以用来访问它们。

顾名思义访问者就是拜访的形式去拜访 Pdf、Word、Xml 类,所以我们 Pdf、Word、Xml 类中需要添加一个 接受访问者的方法 Accept(接受访问者的方法),然后再将当前类的传递给访问者(访问者需要有获取所有数据的权限)。

我们就做到了只要在 Pdf、Word、Xml 类代码中添加一个接受方法,再将类对象传递给访问者

具体的导出工作交个访问者具体方法去做 ,就不会导致 Pdf、Word、Xml 类代码复杂且难以维护。

可能往下看代码容易理解点,那下面就看代码吧。

结构

FileInterface:文件对象接口类。 PdfFile、WordFile、XmlFile:具体的文件类,实现文件接口类,提供访问本身内容的方法。 VisitorInterface:访问者接口类,提供操作接口方法。 FileToTxt:访问者实现类,提供具体向文件的操作方法。

代码示例

文件接口类

interface FileInterface
{
    
    /**
     * 接受者(接受访问者)
     * @return mixed
     * @author chendashengpc
     */
    public function accept(VisitorInterface $visitor);

}

文件具体实现类

// pdf
class PdfFile implements FileInterface
{

    public function accept(VisitorInterface $visitor)
    {
    
        return $visitor->
    PdfToTxt($this);

    }


    /**
     * 打开 PDF 文件内容
     * @return string
     * @author chendashengpc
     */
    public function openPdf(): string
    {
    
        return '我是 Pdf 文件内容';

    }

}


// word
class WordFile implements FileInterface
{

    public function accept(VisitorInterface $visitor)
    {
    
        return $visitor->
    WordToTxt($this);

    }


    /**
     * 打开 Word 文件内容
     * @return string
     * @author chendashengpc
     */
    public function openWord(): string
    {
    
        return '我是 Word 文件内容';

    }

}


// xml
class XmlFile implements FileInterface
{

    public function accept(VisitorInterface $visitor)
    {
    
        return $visitor->
    XmlToTxt($this);

    }


    /**
     * 打开 Xml 文件内容
     * @return string
     * @author chendashengpc
     */
    public function openXml(): string
    {
    
        return '我是 Xml 文件内容';

    }

}

访问者接口类

interface VisitorInterface
{
    
    /**
     * pdf 转 txt
     * @param FileInterface $file
     * @return mixed
     * @author chendashengpc
     */
    public function PdfToTxt(FileInterface $file);
    

    /**
     * Word 转 txt
     * @param FileInterface $file
     * @return mixed
     * @author chendashengpc
     */
    public function WordToTxt(FileInterface $file);
    

    /**
     * Xml 转 txt
     * @param FileInterface $file
     * @return mixed
     * @author chendashengpc
     */
    public function XmlToTxt(FileInterface $file);

}

访问者具体实现类

/**
 * 文件转 txt
 */
class FileToTxt implements VisitorInterface
{

    /**
     * pdf 转 txt
     * @param FileInterface $file
     * @return mixed
     * @author chendashengpc
     */
    public function PdfToTxt(FileInterface $file)
    {
    
        return $file->
    openPdf();

    }


    /**
     * Word 转 txt
     * @param FileInterface $file
     * @return mixed
     * @author chendashengpc
     */
    public function WordToTxt(FileInterface $file)
    {
    
        return $file->
    openWord();

    }


    /**
     * Xml 转 txt
     * @param FileInterface $file
     * @return mixed
     * @author chendashengpc
     */
    public function XmlToTxt(FileInterface $file)
    {
    
        return $file->
    openXml();

    }

}
    

客户端使用

$fileToTxt = new FileToTxt();
    

$pdf = new PdfFile();
    
echo $pdf->
    accept($fileToTxt) . PHP_EOL;
    

$word = new WordFile();
    
echo $word->
    accept($fileToTxt) . PHP_EOL;
    

$xml = new XmlFile();
    
echo $xml->
    accept($fileToTxt) . PHP_EOL;
    

输出

我是 Pdf 文件内容
我是 Word 文件内容
我是 Xml 文件内容

UML

优缺点

优点

  • 开闭原则。 可以引入在不同类对象上执行的新行为,且无需对这些类做出修改。
  • 单一职责原则。可将同一行为的不同版本移到同一个类中。
  • 访问者对象可以在与各种对象交互时收集一些有用的信息。当你想要遍历一些复杂的对象结构(例如对象树),并在结构中的每个对象上应用访问者时, 这些信息可能会有所帮助。

缺点

  • 每次在元素层次结构中添加或移除一个类时,都要更新所有的访问者。
  • 在访问者同某个元素进行交互时,它们可能没有访问元素私有成员变量和方法的必要权限。

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: php设计模式(二十四):访问者模式(Visitor)
本文地址: https://pptw.com/jishu/504560.html
Android AtomicBoolean浅析 php设计模式(二十三):策略模式(Strategy)

游客 回复需填写必要信息