laracon 2018 演讲《Laravel 当中的编程设计模式》笔记

演讲视频

  1. 翻译版:www.pilishen.com/casts/design-patt...
  2. 原视频:www.youtube.com/watch?v=mNl4cMLlpl...

简单介绍

  1. 三大类设计模式:创建型,用于创建类的实例,隐藏创建的细节;结构性,基于继承,不同的对象有相同的作用(功能);行为型,解决对象之间的通讯。
  2. laravel中的设计模式:工厂模式、建造者模式、策略模式、提供者模式

工厂模式

好比做披萨,需要一些原料比如芝士、西红柿。芝士是用牛奶制成的,所以需要有奶牛,需要饲养它、挤奶、加工成芝士等等。本来你只想做披萨,结果不得不把大量的关注点花在如何制作芝士上,用工厂模式就可以很好的解决这类问题。工厂模式用于创建复杂的对象,用统一的方法去实例化它(后期的维护点也只在这里),于是就实现了“披萨”和“芝士”之间的耦合。

laravel中的视图就用了工厂模式,view()方法的源码:

    function view($view = null, $data = [], $mergeData = [])
    {
        $factory = app(ViewFactory::class);

        if (func_num_args() === 0) {
            return $factory;
        }

        return $factory->make($view, $data, $mergeData);
    }

建造者模式

好比开一个披萨店,买各式各样的披萨,每种披萨需要不同的原料、不同的制作工序来制作。既然是开披萨店,当然不能整天忙于制作各种披萨的细节中,你还需要宣传店面、做活动、招呼顾客等等。建造者模式是更高级的工厂模式,它好比是披萨师,他有着制作各种披萨的经验,他会解决做披萨的各种问题,这样做披萨的任务交给他就行了。建造者模式关注于如何一步一步的创建实例,最后总能返回一个你需要的对象。

laravel中的这些服务都是用的建造者模式:

  1. Illuminate\Auth\AuthManager
  2. Illuminate\Broadcasting\BroadcastManager
  3. Illuminate\Cache\CacheManager
  4. Illuminate\Filesystem\FilesystemManager
  5. Illuminate\Mail\MailManager
  6. Illuminate\Notifications\ChannelManager
  7. Illuminate\Queue\QueueManager
  8. Illuminate\Session\SessionManager

以Illuminate\Mail\MailManager为例(我用的laravel 7,所以不是视频讲的Illuminate\Mail\TransportManager)。Mail门面对应的实体是Illuminate\Mail\MailManager,即mail对象的建造者。调用Mail::to()的时候,实际上是调用:

public function __call($method, $parameters)
{
  // 创建一个mailer对象(通过环境变量MAIL_MAILER指定),并且发送邮件
  return $this->mailer()->$method(...$parameters);
}

策略模式

好比给客户送披萨,你可以用人去送,可以用无人机,可以骑车去送,用什么方式送不重要,只要送到就可以了。策略模式就是这样,有不同的策略,不同的实现方式,只要按时送到准确地点就行。策略模式定义一类可替换的实现方式,授权给可用的、不同的算法(实现方式)。
laravel的多语言翻译模块用到了策略模式,Illuminate\Translation\TranslationServiceProvider中:

public function register()
{
  $this->registerLoader();

  $this->app->singleton('translator', function ($app) {
  $loader = $app['translation.loader'];
  // 这里的loader虽然已经写死,但是是可以替换的,只要实现了\Illuminate\Contracts\Translation\Loader即可
  $trans = new Translator($loader, $locale);
  $trans->setFallback($app['config']['app.fallback_locale']);

 return $trans;
  });
}

提供者模式

好比披萨加盟店,你并不懂怎么制作披萨,你可以加盟连锁店,他们告诉你如何制作披萨,原料、制作方法他们会提供给你,他们就相当于供应商。提供者模式,很好的体现了“tell, do not ask”的编程原则。有了提供者模式,我们可以方便的以“服务”的方式扩展我们的应用,就像连上了第三方服务,laravel称之为“组件”。

提供者模式,能够让我们扩展系统,或添加更多的服务,laravel整个框架都是基于这个模式建立起来的。

laravel配置文件的app.providers里面都是大量的服务提供者,都可以算是提供者模式。举例使用一个第三方服务debugbar,看一下Barryvdh\Debugbar\ServiceProvider的register方法(做了简化):

    // 服务注册的时候做了一系列事情,供后续使用
    public function register()
    {
        $configPath = __DIR__ . '/../config/debugbar.php';
        $this->mergeConfigFrom($configPath, 'debugbar');

        $this->app->alias(
            DataFormatter::class,
            DataFormatterInterface::class
        );

        $this->app->singleton(LaravelDebugbar::class, function () {
                $debugbar = new LaravelDebugbar($this->app);
                return $debugbar;
            }
        );

        $this->app->alias(LaravelDebugbar::class, 'debugbar');

        $this->app->singleton('command.debugbar.clear',
            function ($app) {
                return new Console\ClearCommand($app['debugbar']);
            }
        );

        $this->commands(['command.debugbar.clear']);
    }
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 1
zhsh0429

最近也在学习设计模式,在此推荐一个相关网站给大家: refactoringguru

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!