• 技术文章 >后端开发 >php教程

    一文了解PHP中的享元模式

    青灯夜游青灯夜游2021-07-14 19:32:55转载522
    在之前的文章《聊聊PHP中的代理模式(正向代理和反向代理)》中我们介绍了PHP中的代理模式,下面本篇文章带大家了解一下PHP设计模式中的享元模式。

    享元模式,“享元”这两个字在中文里其实并没有什么特殊的意思,所以我们要把它拆分来看。“享”就是共享,“元”就是元素,这样一来似乎就很容易理解了,共享某些元素嘛。

    Gof类图及解释

    GoF定义:运用共享技术有效地支持大量细粒度的对象

    GoF类图

    1.jpg

    代码实现

    interface Flyweight
    {
        public function operation($extrinsicState) : void;
    }
    
    class ConcreteFlyweight implements Flyweight
    {
        private $intrinsicState = 101;
        function operation($extrinsicState) : void
        {
            echo '共享享元对象' . ($extrinsicState + $this->intrinsicState) . PHP_EOL;
        }
    }
    
    class UnsharedConcreteFlyweight implements Flyweight
    {
        private $allState = 1000;
        public function operation($extrinsicState) : void
        {
            echo '非共享享元对象:' . ($extrinsicState + $this->allState) . PHP_EOL;
        }
    }

    定义共享接口以及它的实现,注意这里有两个实现,ConcreteFlyweigh进行状态的共享,UnsharedConcreteFlyweight不共享或者说他的状态不需要去共享

    class FlyweightFactory
    {
        private $flyweights = [];
    
        public function getFlyweight($key) : Flyweight
        {
            if (!array_key_exists($key, $this->flyweights)) {
                $this->flyweights[$key] = new ConcreteFlyweight();
            }
            return $this->flyweights[$key];
        }
    }

    保存那些需要共享的对象,做为一个工厂来创建需要的共享对象,保证相同的键值下只会有唯一的对象,节省相同对象创建的开销

    $factory = new FlyweightFactory();
    
    $extrinsicState = 100;
    $flA = $factory->getFlyweight('a');
    $flA->operation(--$extrinsicState);
    
    $flB = $factory->getFlyweight('b');
    $flB->operation(--$extrinsicState);
    
    $flC = $factory->getFlyweight('c');
    $flC->operation(--$extrinsicState);
    
    $flD = new UnsharedConcreteFlyweight();
    $flD->operation(--$extrinsicState);

    客户端的调用,让外部状态$extrinsicState能够在各个对象之间共享

    还是说到科技以换壳为本这件事上。毕竟,大家都还是喜欢各种颜色的手机来彰显自己的个性。之前说过,如果每种颜色我们都要做一条生产线的话那岂不是一项巨大的投入。还好,每个型号我们的工厂(享元工厂)只生产最基本的背景壳(对象),然后通过专门的印刷线(状态变化)来进行上色不就好啦!嗯,下一款Iphone早晚也会模仿我们的,看来我们得先把各种金、各种土豪色集齐才行,说不定还能召唤神龙呢!!

    完整代码:https://github.com/zhangyue0503/designpatterns-php/blob/master/13.flyweights/source/flyweights.php

    实例

    果然不出意外的我们还是来发短信,这回的短信依然使用的阿里云和极光短信来进行发送,不过这次我们使用享元模式来实现,这里的享元工厂我们保存了两种不同类型的对象哦,通过内外状态来让它们千变万化吧!

    短信发送类图

    1.png

    完整源码:https://github.com/zhangyue0503/designpatterns-php/blob/master/13.flyweights/source/flyweights-message.php

    <?php
    
    interface Message
    {
        public function send(User $user);
    }
    
    class AliYunMessage implements Message
    {
        private $template;
        public function __construct($template)
        {
            $this->template = $template;
        }
        public function send(User $user)
        {
            echo '使用阿里云短信向' . $user->GetName() . '发送:';
            echo $this->template->GetTemplate(), PHP_EOL;
        }
    }
    
    class JiGuangMessage implements Message
    {
        private $template;
        public function __construct($template)
        {
            $this->template = $template;
        }
        public function send(User $user)
        {
            echo '使用极光短信向' . $user->GetName() . '发送:';
            echo $this->template->GetTemplate(), PHP_EOL;
        }
    }
    
    class MessageFactory
    {
        private $messages = [];
        public function GetMessage(Template $template, $type = 'ali')
        {
            $key = md5($template->GetTemplate() . $type);
            if (!key_exists($key, $this->messages)) {
                if ($type == 'ali') {
                    $this->messages[$key] = new AliYunMessage($template);
                } else {
                    $this->messages[$key] = new JiGuangMessage($template);
                }
            }
            return $this->messages[$key];
        }
    
        public function GetMessageCount()
        {
            echo count($this->messages);
        }
    }
    
    class User
    {
        public $name;
        public function GetName()
        {
            return $this->name;
        }
    }
    
    class Template
    {
        public $template;
        public function GetTemplate()
        {
            return $this->template;
        }
    }
    
    // 内部状态
    $t1 = new Template();
    $t1->template = '模板1,不错哟!';
    
    $t2 = new Template();
    $t2->template = '模板2,还好啦!';
    
    // 外部状态
    $u1 = new User();
    $u1->name = '张三';
    
    $u2 = new User();
    $u2->name = '李四';
    
    $u3 = new User();
    $u3->name = '王五';
    
    $u4 = new User();
    $u4->name = '赵六';
    
    $u5 = new User();
    $u5->name = '田七';
    
    // 享元工厂
    $factory = new MessageFactory();
    
    // 阿里云发送
    $m1 = $factory->GetMessage($t1);
    $m1->send($u1);
    
    $m2 = $factory->GetMessage($t1);
    $m2->send($u2);
    
    echo $factory->GetMessageCount(), PHP_EOL; // 1
    
    $m3 = $factory->GetMessage($t2);
    $m3->send($u2);
    
    $m4 = $factory->GetMessage($t2);
    $m4->send($u3);
    
    echo $factory->GetMessageCount(), PHP_EOL; // 2
    
    $m5 = $factory->GetMessage($t1);
    $m5->send($u4);
    
    $m6 = $factory->GetMessage($t2);
    $m6->send($u5);
    
    echo $factory->GetMessageCount(), PHP_EOL; // 2
    
    // 加入极光
    $m1 = $factory->GetMessage($t1, 'jg');
    $m1->send($u1);
    
    $m2 = $factory->GetMessage($t1);
    $m2->send($u2);
    
    echo $factory->GetMessageCount(), PHP_EOL; // 3
    
    $m3 = $factory->GetMessage($t2);
    $m3->send($u2);
    
    $m4 = $factory->GetMessage($t2, 'jg');
    $m4->send($u3);
    
    echo $factory->GetMessageCount(), PHP_EOL; // 4
    
    $m5 = $factory->GetMessage($t1, 'jg');
    $m5->send($u4);
    
    $m6 = $factory->GetMessage($t2, 'jg');
    $m6->send($u5);
    
    echo $factory->GetMessageCount(), PHP_EOL; // 4

    说明

    原文地址:https://juejin.cn/post/6844903965814259726

    作者:硬核项目经理

    推荐学习:《PHP视频教程

    以上就是一文了解PHP中的享元模式的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金--硬核项目经理,如有侵犯,请联系admin@php.cn删除
    上一篇:深入了解PHP中的缓存技术 下一篇:使用PHP要如何操作Redis?基本操作方法介绍
    第16期线上培训班

    相关文章推荐

    • php怎么实现文件缩略图• php关闭警告提示的方法• php怎么清除文件内容• php array怎么增加元素• php怎么修改文件所有者• 深入了解PHP中的缓存技术

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网