zoukankan      html  css  js  c++  java
  • 使用 Laravel 的 监听者模式实现缓存机制的松散耦合

    使用 Laravel 的 监听者模式实现缓存机制的松散耦合

    一、总结

    一句话总结:

    1、既然要实现松散耦合的缓存机制,那就是要做到有没有缓存都没事。有缓存的话就走缓存,然后那边的模块内部实现一个包括过期时间呀啥啥的缓存机制,没有收到缓存模块的响应的时候就继续走原来的应用逻辑,一样可以正常响应。
    2、因为我们是要实现应用逻辑与缓存逻辑的解耦,所以正常应用逻辑内是不能有对那些缓存的依赖的。那么我们要通过什么来和缓存模块通信呢?巧的是,Laravel 正好提供了基于 Event 和 Listener 的观察者模式,我们就可以用这种设计模式来解耦缓存模块。

    二、使用 Laravel 的 监听者模式实现缓存机制的松散耦合

    转自或参考:使用 Laravel 的 监听者模式实现缓存机制的松散耦合 - PRIN 的专栏 - SegmentFault 思否
    https://segmentfault.com/a/1190000006916271

    既然要实现松散耦合的缓存机制,那就是要做到有没有缓存都没事。有缓存的话就走缓存,然后那边的模块内部实现一个包括过期时间呀啥啥的缓存机制,没有收到缓存模块的响应的时候就继续走原来的应用逻辑,一样可以正常响应。

    因为我们是要实现应用逻辑与缓存逻辑的解耦,所以正常应用逻辑内是不能有对那些缓存的依赖的。那么我们要通过什么来和缓存模块通信呢?巧的是,Laravel 正好提供了基于 Event 和 Listener 的观察者模式,我们就可以用这种设计模式来解耦缓存模块。

    首先,我们在即将获取一个可能需要缓存的数据之前,触发一个 GetDataEvent(举个栗子),接下来判断这个 Event 是否返回了响应,如有则使用响应的内容,没有的话就继续正常的应用逻辑来获取数据。

    譬如说,我们需要把皮肤的预览图给缓存下来,而不是每次都去生成:

    <?php
    
    namespace AppEvents;
    
    use AppEventsEvent;
    use AppModelsTexture;
    use IlluminateQueueSerializesModels;
    
    class GetSkinPreview extends Event
    {
        use SerializesModels;
    
        public $texture;
    
        public $size;
    
        /**
         * 这里我们并没有做什么,就是把实例化时传进来的参数保存到对象里去
         *
         * @return void
         */
        public function __construct(Texture $texture, $size)
        {
            $this->texture = $texture;
            $this->size    = $size;
        }
    }
    
    // 控制器中的方法
    public function preview($tid, $size = 250)
    {
        // 触发事件
        $responses = Event::fire(new GetSkinPreview($t, $size));
    
        // 当然,如果你有多个 Listener 的话,在这里你可能需要遍历 Event 所返回的响应
        if (isset($responses[0]) && $responses[0] instanceof SymfonyComponentHttpFoundationResponse) {
            // 这个返回的响应类型是看你自己对 Event 的需求的
            // 比如这里我们需要 Listener 返回一个 Http 响应流
            return $responses[0];
        } else {
            /* 原来业务逻辑中的生成预览 */
    
            return Response::png();
        }
    }

    而这个 GetDataEvent,我们是可以注册 Listener 上去的,具体如何添加 Event 和 Listener 请参考 Laravel 文档。假设我们在这里给这个事件注册了一个 CacheDataListener,那么在 GetDataEvent 这个事件在应用逻辑中被触发的时候,Laravel 的 Event Dispatcher 就会把事件分发到我们刚刚注册的监听器里,我们就可以在监听器的 handle 方法中处理缓存逻辑并返回缓存后的数据了。

    <?php
    
    namespace AppListeners;
    
    use Storage;
    use AppEventsGetSkinPreview;
    
    class CacheSkinPreview
    {
        /**
         * 处理缓存逻辑并返回一个 Http 响应流
         *
         * @param  GetSkinPreview  $event
         * @return void
         */
        public function handle(GetSkinPreview $event)
        {
            $tid = $event->texture->tid;
    
            if (!Storage::disk('cache')->has("preview/$tid")) {
                /* 这里生成预览并保存到缓存文件 */
            }
    
            return Response::png(Storage::disk('cache')->get("preview/$tid"));
        }
    }

    这样下来,我们就可以让应用逻辑和缓存逻辑(差不多)完全分离开来,想要使用其他的缓存驱动,例如 Redis 的话,只要新建一个 Listener 并监听 GetDataEvent 就可以了。你甚至可以把缓存机制放到插件里去,而这也就是我本来的目的(笑)

     
  • 相关阅读:
    部署 AppGlobalResources 到 SharePoint 2010
    还原一个已删除的网站集
    使用仪表板设计器配置级联筛选器 (SharePoint Server 2010 SP1)
    File or arguments not valid for site template
    Pex and Moles Documentation
    Content Query Webpart匿名访问
    Running Moles using NUnit Console from Visual Studio
    Calling a WCF Service using jQuery in SharePoint the correct way
    Updating Content Types and Site Columns That Were Deployed as a Feature
    asp.net中判断传过来的字符串不为空的代码
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/12624219.html
Copyright © 2011-2022 走看看