次の状況を想像してください。
セッターを使用する
<?php class Page { /** * @var string */ private $content; /** * @param $content */ public function setContent($content) { $this->content = $content; } } class PageBuilder { /** * @var Page */ private $page; /** * @param $page */ public function setPage($page) { $this->page = $page; } /** * @param $content * @return $this */ public function setContent($content) { $this->page->setContent($content); return $this; } /** * @return Page */ public function build() { return $this->page; } }
$pageBuilder = new PageBuilder(); $pageBuilder->setPage(new Page()); $pageBuilder->setContent('Test content'); $pageBuilder->build();
この例は、 $ pageBuilder-> build()が潜在的に危険であり、 $ pageBuilder-> setPage(new Page())が以前に呼び出されなかった場合、致命的なエラーにつながる可能性があることを示しています。 もう1つのよくある間違いは、 init()または初期化()メソッドの使用です。
初期化子の使用
class Page { // Class } class PageBuilder { /** * @var Page */ private $page; /** * Initialization */ public function init() { $this->page = new Page(); } /** * @param $content * @return $this */ public function setContent($content) { $this->page->setContent($content); return $this; } /** * @return Page */ public function build() { return $this->page; } }
$pageBuilder = new PageBuilder(); $pageBuilder->init(); $pageBuilder->setContent('Test content'); $pageBuilder->build();
init()メソッドの呼び出しを忘れると、問題も発生します。 このコードは、貧弱なアプリケーションアーキテクチャの好例です。 初期化メソッドは、定義によるものではないコンストラクターのように動作しようとします。
時間的カップリングを回避するには、常にルールを使用する必要があります。
- クラスインスタンスは、作成後すぐに使用できる状態になっている必要があります。
- コンストラクターは、クラスプロパティの初期化以外のロジックを実行しないでください。
コンストラクター依存性注入
このソリューションは、ほとんどの場合最適であり、推奨されます。 Symfony、Laravel、またはその他の最新のフレームワークの依存性注入メカニズムを使用できます。
コンストラクター注入
class Page { // Class } class PageBuilder { /** * @var Page */ private $page; /** * PageBuilder constructor. * @param Page $page */ public function __construct(Page $page) { $this->page = $page; } // - } $pageBuilder = new PageBuilder(new Page()); $pageBuilder->setContent('Test content'); $pageBuilder->build();
抽象工場
抽象ファクトリーを追加して、コードを少し変更します。
抽象工場
<?php class Page { // Class } class PageBuilder { /** * @var Page */ private $page; /** * PageBuilder constructor. * @param Page $page */ public function __construct(Page $page) { $this->page = $page; } /** * @param $content * @return $this */ public function setContent($content) { $this->page->setContent($content); return $this; } /** * @return Page */ public function build() { return $this->page; } } class PageBuilderFactory implements FactoryInterface { /** * @param Page|null $page * @return PageBuilder */ public function create(Page $page = null) { if (null === $page) { $page = new Page(); } return new PageBuilder($page); } } $pageBuilderFactory = new PageBuilderFactory(); $pageBuilder = $pageBuilderFactory->create(); $pageBuilder->setContent('Test content'); $pageBuilder->build();
ご覧のとおり、 Pageクラスのインスタンスは明示的な呼び出しなしで作成され、ビルダーで使用できます。
おわりに
アプリケーションの複雑さ、コードレビュー、またはその他の要因に関係なく、一時的なカップリングは常に回避する必要があります。 また、コンストラクターは注入に関連するロジックのみを実行する必要があることを忘れないでください。 そうしないと、クラスのインスタンス化中にパフォーマンスが低下するリスクがあります。