ホームページ >バックエンド開発 >PHPチュートリアル >PHP の制御反転と依存性注入の例

PHP の制御反転と依存性注入の例

小云云
小云云オリジナル
2018-03-22 09:23:192433ブラウズ

この記事では、主に PHP 制御の反転と依存関係の挿入の例を紹介します。依存関係の挿入の目的は、コードのテスト、管理、拡張を改善するための疎結合ソフトウェア アーキテクチャを実現することです。

制御の反転: 呼び出し元が呼び出し先の支援を必要とする場合、従来のプログラミング プロセスでは通常、呼び出し元は呼び出し先のインスタンスを作成しますが、ここでは呼び出し先の作成作業は呼び出し元によって行われなくなります。しかし、呼び出し先の作成は呼び出し元の外部に移動されるため、呼び出し先の作成が反転され、呼び出し先の作成に対する呼び出し元の制御が削除されるため、制御の反転と呼ばれます。

依存性注入: 制御の反転を実現するための通常の解決策は、呼び出し先インスタンスの作成作業を IoC コンテナーに任せてから、呼び出し先を呼び出し元に (コンストラクター/メソッド注入の実装を通じて) 注入することです。このプロセスは、依存関係の注入と呼ばれます。依存関係の注入は、制御の反転の実装です。一般的な注入方法には、セッター、コンストラクター注入、プロパティ注入の 3 つがあります。

コンテナ: オブジェクトの生成、リソースの取得、破棄などのライフサイクルを管理し、オブジェクト間の依存関係を確立し、オブジェクトの読み込みを遅延させることができます。より有名なものは、PHP-DI と Pimple です。

コードデモ IoC:

アプリケーションにストレージ要件があると仮定すると、低レベルモジュール API が高レベルアプリケーションで直接呼び出される場合、アプリケーションは低レベルモジュールに依存するようになります。

<?php
/**
 * 高层
 */
class App
{
    private $writer;

    public function __construct()
    {
        $this->writer = new FloppyWriter();
    }

    public function save()
    {
        $this->writer->saveToFloppy();
    }
}

/**
 * 低层,软盘存储
 */
class FloppyWriter
{
    public function saveToFloppy()
    {
        echo __METHOD__;
    }
}

$app = new App();
$app->save(); // FloppyWriter::saveToFloppy

プログラムを別のプラットフォームに移植する予定で、そのプラットフォームが記憶媒体として USB ディスクを使用すると仮定すると、プログラムは直接再利用できず、変更する必要があります。この場合、低レベルの変化により、高レベルの変化も追随することになり、これは悪い設計です。プログラムは具体的な実装ではなく、抽象的なインターフェイスに依存する必要があります。コードのデモをご覧ください:

<?php
/**
 * 接口
 */
interface IDeviceWriter
{
    public function saveToDevice();
}

/**
 * 高层
 */
class App
{
    /**
     * @var IDeviceWriter
     */
    private $writer;

    /**
     * @param IDeviceWriter $writer
     */
    public function setWriter($writer)
    {
        $this->writer = $writer;
    }

    public function save()
    {
        $this->writer->saveToDevice();
    }
}

/**
 * 低层,软盘存储
 */
class FloppyWriter implements IDeviceWriter
{

    public function saveToDevice()
    {
        echo __METHOD__;
    }
}

/**
 * 低层,USB盘存储
 */
class UsbDiskWriter implements IDeviceWriter
{

    public function saveToDevice()
    {
        echo __METHOD__;
    }
}

$app = new App();
$app->setWriter(new UsbDiskWriter());
$app->save(); // UsbDiskWriter::saveToDevice

$app->setWriter(new FloppyWriter());
$app->save(); // FloppyWriter::saveToDevice

制御は実際の FloppyWriter から抽象的な IDeviceWriter インターフェイスに転送され、アプリは IDeviceWriter インターフェイスに依存し、FloppyWriter と UsbDiskWriter も IDeviceWriter インターフェイスに依存します。
これは IoC です。変更に直面しても、高レベルはコード行を変更する必要がなく、低レベルに依存せず、インジェクションに依存するため、DI が発生します。

このコンポーネントに多くの依存関係がある場合、依存関係を渡すために複数のパラメーター セッター メソッドを作成する必要があり、コードの保守が困難になります。

<?php
//创建依赖实例
$request = new Request();
$filter = new Filter();

//把实例作为参数传递给构造函数
$some = new SomeComponent($request, $filter);

$some->setRequest($request);
$some->setFilter($filter);


解決策は、依存インスタンスにコンテナを提供することです。このコンテナはグローバル レジストリとして機能し、特定のインスタンスではなくコンテナに挿入されます。

<?php
class SomeComponent
{

    protected $_di;

    public function __construct($di)
    {
        $this->_di = $di;
    }

    public function someRequest()
    {

        // 请求实例
        $connection = $this->_di->get(&#39;request&#39;);

    }

    public function someOtherRequest()
    {

        // 请求实例
        $connection = $this->_di->get(&#39;request&#39;);

        // 过滤器实例
        $filter = $this->_di->get(&#39;filter&#39;);

    }

}

$di = new DI();

//在容器中注册一个request服务
$di->set(&#39;request&#39;, function() {
    return new Request(array(
        "test" => "test"
    ));
});

//在容器中注册一个filter服务
$di->set(&#39;filter&#39;, function() {
    return new Filter();
});

//把传递服务的容器作为唯一参数传递给组件
$some = new SomeComponent($di);
$some->someRequest();

このコンポーネントは、必要なサービスを簡単に取得できるようになりました。サービスは遅延読み込みを使用し、必要な場合にのみ初期化されるため、サーバー リソースも節約されます。このコンポーネントは現在、高度に分離されています。
関連する推奨事項:

PHP の依存関係の挿入と制御の反転の分析

PHP の依存関係の挿入 (DI) と制御の反転 (IoC) のサンプル チュートリアル

PHP の制御の反転と依存関係の挿入

以上がPHP の制御反転と依存性注入の例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。