资讯专栏INFORMATION COLUMN

PHP设计模式之访问者模式

用户83 / 3078人阅读

摘要:访问者模式解决的问题在我们的代码编写过程当中,经常需要对一些类似的对象添加一些的代码,我们以一个计算机对象打印组成部分为例来看下抽象基类获取名称类内存类键盘类计算机类循环打印各个组成部分这个时候上面的代码看上去好像很完美的样子,但是问

访问者模式解决的问题

在我们的代码编写过程当中,经常需要对一些类似的对象添加一些的代码,我们以一个计算机对象打印组成部分为例来看下:

    /**
    * 抽象基类
    */
    abstract class Unit
    {
        /**
        *获取名称
        */
        abstract public function getName();

    }

    /**
    * Cpu类
    */
    class Cpu extends Unit
    {
        public function getName()
        {
            return "i am cpu";
        }
    }

    /**
    * 内存类
    */
    class Memory extends Unit
    {
        public function getName()
        {
            return "i am memory";
        }
    }

    /**
    * 键盘类
    */
    class Keyboard extends Unit
    {
        public function getName()
        {
            return "i am keyboard";
        }
    }

    /**
    * 计算机类
    */
    class Computer
    {
        protected $_items = [];

        public function add(Unit $unit)
        {
            $this->_items[] = $unit;
        }

        public function print()
        {
            // 循环打印各个组成部分
            foreach ($this->_items as $item) {
                $item->getName();
            }
        }
    }

这个时候上面的代码看上去好像很完美的样子,但是问题来了,现在我们不但需要打印组成部分,还需要保存各个组件到数据库,不仅如此,还需要打印各个组件的价格;此时如果在Unit基类中添加getPrice()和save()方法,也能实现我们想要的功能,但是这样做也存在问题,你并不知道还需要新增什么操作,如果每新增一个操作都用这样的方法来新增,我们的类会变得越来越臃肿。

访问者模式的实现

而访问者模式就是为了解决这个问题的,他把数据结构和作用于结构之上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化,我们来看下面改良过得代码:

    /**
    * 抽象基类
    */
    abstract class Unit
    {
        /**
        * 获取名称
        */
        abstract public function getName();

        /**
        * 用来接受访问者对象,回调访问者的visit方法
        * 非常关键的方法
        */
        public function accept(Visitor $visitor)
        {
            $method = visit . get_class($this);
            if (method_exists($visitor, $method)) {
                $visitor->$method($this);
            }
        }
    }

    /**
    * Cpu类
    */
    class Cpu extends Unit
    {
        public function getName()
        {
            return "i am cpu";
        }
    }

    /**
    * Memory类
    */
    class Memory extends Unit
    {
        public function getName()
        {
            return "i am memory";
        }
    }

    /**
    * Keyboard类
    */
    class Keyboard extends Unit
    {
        public function getName()
        {
            return "i am keyboard";
        }
    }
    
    /**
    * Keyboard类
    */
    interface Visitor
    {
        public function visitCpu(Cpu $cpu);
        public function visitMemory(Memory $memory);
        public function visitKeyboard(Keyboard $keyboard);
    }

    /**
    * 
    */
    class PrintVisitor implements Visitor
    {
        public function visitCpu(Cpu $cpu)
        {
            echo "hello, " . $cpu->getName() . "
";
        }

        public function visitMemory(Memory $memory)
        {
            echo "hello, " . $memory->getName() . "
";
        }

        public function visitKeyboard(Keyboard $keyboard)
        {
            echo "hello, " . $keyboard->getName() . "
";
        }
    }

    /**
    * 
    */
    class Computer
    {
        protected $_items = [];

        public function add(Unit $unit)
        {
            $this->_items[] = $unit;
        }
        
        /**
        * 调用各个组件的accept方法
        */
        public function accept(Visitor $visitor)
        {
            foreach ($this->_items as $item) {
                $item->accept($visitor);
            }
        }
    }

    $computer = new Computer();
    $computer->add(new Cpu());
    $computer->add(new Memory());
    $computer->add(new Keyboard());

    $printVisitor = new PrintVisitor();
    $computer->print($printVisitor);

    // 以上的代码将打印出    
    hello, i am cpu
    hello, i am memory
    hello, i am keyboard
总结

经过上面的改良之后,我们要扩展就变得非常容易,如果我们需要新增保存到数据库的方法,可以在新增一个实现了Visitor的类,比如SaveVisitor,在该类中来实现保存的方法,等于我们把该类和该类中的一些操作解藕了出来,而集合了类操作的对象就是访问者。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/21377.html

相关文章

  • PHP设计模式迭代器模式

    摘要:概念迭代器模式,又叫做游标模式。另外,当需要对聚集有多种方式遍历时,可以考虑去使用迭代器模式。迭代器模式为遍历不同的聚集结构提供如开始下一个是否结束当前哪一项等统一的接口。 概念 迭代器模式(Iterator),又叫做游标(Cursor)模式。提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。 当你需要访问一个聚合对象,而且不管这些对象是什么都需要遍历的时候,就...

    陆斌 评论0 收藏0
  • php 设计模式 访问者模式

    摘要:概念访问者模式实际上是让外部类能够获取树形结构的每个节点的对象,对每个对象进行操作的模式,他能让我们在不改动原有树形结构的基础上扩展功能。 概念: 访问者模式实际上是让外部类能够获取树形结构的每个节点的对象,对每个对象进行操作的模式, 他能让我们在不改动原有树形结构的基础上扩展功能。比如统计等等 在这种模式下,必须有的几个要素: 1: 具体的元素对象, 访问者实际要访问的位置(即节...

    zzir 评论0 收藏0
  • PHP基础

    摘要:分别为适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。设计模式五适配器模式适配器模式将某个对象的接生成器和协程的实现在这篇文章中,作者针对那些比较难以理解的概念,以一个更为通俗的方式去讲明白。。 PHP 源码注解 PHP 的详细源码注解 PHP 字符串操作整理 一些有关字符串的常用操作。 Redis 常见七种使用场景 (PHP 实战) 这篇文章主要介绍利用 R...

    HtmlCssJs 评论0 收藏0
  • PHP设计模式系列入门

    摘要:设计模式系列之入门设计模式是一套被反复使用多数人知晓的经过分类编目的代码设计经验的总结。毫无疑问,设计模式于己于他人于系统都是多赢的设计模式使代码编制真正工程化设计模式是软件工程的基石脉络,如同大厦的结构一样。 PHP设计模式系列之入门 设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易...

    animabear 评论0 收藏0
  • PHP 实战设计模式PHP 中的设计模式

    摘要:事实上,设计模式的解释如下另一方面,设计模式提供了一种广泛的可重用的方式来解决我们日常编程中常常遇见的问题。原型模式有些时候,部分对象需要被初始化多次。 本文为翻译文章 原文地址:Design Patterns in PHP如果打算学习PHP的童鞋可以参考下笔者的编程语言学习知识体系要点列表 本文主要讨论下Web开发中,准确而言,是PHP开发中的相关的设计模式及其应用。有经验的开发者肯...

    2450184176 评论0 收藏0

发表评论

0条评论

用户83

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<