laracon 2018 演講《Laravel 當中的程式設計設計模式》筆記

xing393939發表於2020-06-20

演講影片

  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 協議》,轉載必須註明作者和本文連結

相關文章