ホームページ  >  記事  >  バックエンド開発  >  PHP の依存関係の注入、ロード順序は考慮されなくなり、load_PHP チュートリアルも不要になりました。

PHP の依存関係の注入、ロード順序は考慮されなくなり、load_PHP チュートリアルも不要になりました。

WBOY
WBOYオリジナル
2016-07-12 09:00:40652ブラウズ

PHP の依存関係の注入、ロード順序を考慮しなくなり、ロードが不要になります

このトピックについて話す前に、比較的高度なアイデアについて話させてください - 「依存関係逆転の原則

「依存関係の逆転はソフトウェア設計のアイデアです。従来のソフトウェアでは、上位層のコードは下位層のコードに依存します。下位層のコードが変更されると、それに応じて上位層のコードも変更する必要があるため、メンテナンスはコストが高くなります。依存関係逆転の原則は、上位層が下位層に依存するのではなく、インターフェイスに依存する必要があるというものです。つまり、上位層のコードがインターフェイスを定義し、下位層のコードがインターフェイスを実装します。 、下位層が上位層のインターフェースに依存するようになり、結合が減少し、システムの柔軟性が向上します。」

上記の説明は少し間違っています。この理論を以下の実際のコードで説明しましょう

たとえば、このような要件がある場合、ユーザー登録が完了した後にメールを送信する必要がある場合、次のコードになります:

まず、メールクラス「Email.class.php」があります

リーリー

次にクラス「Register.class.php」を登録します

リーリー

それでは登録を開始してください

リーリー

この機能をすぐにオンラインにすると、すべてがうまくいくようです...xxx 日後、製品担当者は、メールの送信は良くないので、テキストを送信するものを使用する必要があると言いました。それなら簡単だと言われたので、「メール」カテゴリを変更します...

数日後、製品スタッフは、テキストメッセージの送信コストが高すぎるため、代わりに電子メールを使用したほうが良いと言った...このとき、10,000の草泥馬が私の心を駆け抜けました...

このようなことは製品犬によく起こりますが、すべてなくなります...

上記のシナリオの問題は、毎回「Mail」クラスを変更する必要があり、コードの再利用性が非常に低く、上位レベルが下位レベルに過度に依存していることです。次に、上位層が開発したインターフェースを最下位層が継承し、上位層がそのインターフェースに依存する「依存関係逆転原理」を考えます。

リーリー リーリー リーリー リーリー

以下からメッセージの送信を開始してください

リーリー

上記のコードは、コンストラクター注入メソッドを使用して、メッセージ送信クラスへの「Register」の依存関係を解決します。そのため、インターフェースに「send」メソッドを実装している限り、テキストメッセージを送信するインターフェースにのみ依存します。どのような方法で送っても構いません。上記の例では、「

inject」というアイデアを使用しています。これは、あるクラスのインスタンスを別のクラスのインスタンスに注入する注射器のようなものです。もちろん、「依存関係逆転の原則」は常に実装されています。 「Injection」は、コンストラクターを介して注入するだけでなく、属性注入によっても注入できます。上記では、「setter」を介して「mailObj」属性に値を動的に割り当てることができます。

上でたくさん読みましたが、注意深い読者はタイトルに「

ロード順序を考慮しなくなりました」という言葉を見つけるかもしれませんが、まだ上記のロード順序を考慮する必要はありませんか?最初にクラスを作成し、次に登録されたクラスを導入してインスタンス化しますか? カテゴリが複数あると、やはり目まいがしてしまいます。

実際、そのようなケースはたくさんあります。最初はクラスの数が限られていましたが、徐々に機能が増え、人が増え、このクラスを使用するには、まず導入する必要があります。そのクラス、そして順序が正しいことを確認してください。 「a は b に依存し、b は c に依存し、c は d に依存し、d は e に依存する」という例があります。「a」のインスタンスを取得するには、「e、d、c、b」を導入する必要があります。インスタンス化の場合、昔の従業員はこの落とし穴を知っていて、それを飛び越えました。ある日、新しい人が入ってきて、「a」をインスタンス化しようとしましたが、エラーが発生し続け、この時点では「a」のビジネス ロジックを確認することしかできませんでした。彼は、最初に 'b' のインスタンスを取得する必要があることを知っていて、次に 'b' のビジネス ロジックを調べました。そして... 1 日経っても、まだ 'a' のインスタンスを取得できませんでした。と、そこにリーダーがやって来ました…

では、この問題は新人の技術力が低かったのか、それとも当時の建築家のレベルが低かったのか?

次に、ロード順序を考慮せずに実装する方法のトピックに移りましょう。実装する前に、ロード順序を考慮しないということは、プログラムが自動的にロードされ、自動的にインスタンス化されることを意味することを理解する必要があります。クラスをインスタンス化するには、必要なすべてのパラメーターが '__construct' 関数に渡されていることを確認してください。クラス内の他のクラスを参照する場合は、それらをコンストラクターにも挿入する必要があります。そうしないと、呼び出し時にエラーが発生します。次に、クラスのインスタンス化に必要なパラメーター、他の依存クラスまたはオブジェクト、インスタンス化後の各クラスへの参照を保存するクラスが必要になります

クラスの名前はボックス「Container.class.php」で、その内容は次のとおりです:

リーリー

以下は「Instance」クラスの内容です。これは主にクラス名を記録し、インスタンスを取得する必要があるかどうかを示すために使用されます

リーリー

その後、クラスのインスタンスに属性を動的に追加する機能を「Container.class.php」に実装しました。属性を動的に追加するには、マジック メソッド「__set」を使用する必要があるため、依存関係を使用するすべてのクラスに属性が追加されます。このメソッドを実装するには、まず基本クラス「Base.class.php」を定義します。内容は次のとおりです

リーリー

次に、クラス 'A、B、C' を実装します。クラス A のインスタンスはクラス B のインスタンスに依存し、クラス B のインスタンスはクラス C のインスタンスに依存します

「A.class.php」

リーリー

「B.class.php」

リーリー

「C.class.php」

<span>class</span> C  <span>extends</span><span> Base{
    </span><span>public</span> <span>function</span><span> test()
    {
        </span><span>echo</span> 'this is C!'<span>;
    }
}de</span>

然后我们在'index.php'中获取'A'的实例,要实现自动加载,需要使用SPL类库的'spl_autoload_register'方法,代码如下

<span>function</span> autoload(<span>$className</span><span>)
{
    </span><span>include_once</span> <span>$className</span> . '.class.php'<span>;
}
spl_autoload_register(</span>'autoload', <span>true</span>, <span>true</span><span>);
</span><span>$container</span> = <span>new</span><span> Container;

</span><span>$a</span> = <span>$container</span>->get('A'<span>);
</span><span>$a</span>->test();<span>//</span><span>输出 'this is C!'</span>

上面的例子看起来是不是很爽,根本都不需要考虑'B','C' (当然,这里B,C 除了要使用相应类的实例外,没有其他参数,如果有其他参数,必须显要调用'$container->set(xx)'方法进行注册,为其制定实例化必要的参数)。有细心同学可能会思考,比如我在先获取了'A'的实例,我在另外一个地方也要获取'A'的实例,但是这个地方'A'的实例需要其中某个属性不一样,我怎么做到?

你可以看到'Container' 类的 'get' 方法有其他两个参数,'$params' 和 '$properties' , 这个'$properties' 即可实现刚刚的需求,这都依赖'__set'魔术方法,当然这里你不仅可以注册类,也可以注册方法或者对象,只是注册方法时要使用回调函数,例如

<span>$container</span>->set('foo', <span>function</span>(<span>$container</span>, <span>$params</span>, <span>$config</span><span>){
    </span><span>print_r</span>(<span>$params</span><span>);
    </span><span>print_r</span>(<span>$config</span><span>);
});

</span><span>$container</span>->get('foo', <span>array</span>('name' => 'foo'), <span>array</span>('key' => 'test'));

还可以注册一个对象的实例,例如

<span>class</span><span> Test
{
    </span><span>public</span> <span>function</span><span> mytest()
    {
        </span><span>echo</span> 'this is a test'<span>;
    }
}

</span><span>$container</span>->set('testObj', <span>new</span><span> Test());

</span><span>$test</span> = <span>$container</span>->get('testObj'<span>);
</span><span>$test</span>->mytest();

 

 以上自动加载,依赖控制的大体思想就是将类所要引用的实例通过构造函数注入到其内部,在获取类的实例的时候通过PHP内建的反射解析构造函数的参数对所需要的类进行加载,然后进行实例化,并进行缓存以便在下次获取时直接从内存取得

 

以上代码仅仅用于学习和实验,未经严格测试,请不要用于生产环境,以免产生未知bug

 

鄙人才疏学浅,有不足之处,欢迎补足!

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1092697.htmlTechArticlePHP 依赖注入,从此不再考虑加载顺序,从此不再加载 说这个话题之前先讲一个比较高端的思想--' 依赖倒置原则 ' "依赖倒置是一种软件设计...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。