ホームページ  >  記事  >  バックエンド開発  >  PHPデザインパターンについて ~アダプターメソッドの詳細説明~

PHPデザインパターンについて ~アダプターメソッドの詳細説明~

零到壹度
零到壹度オリジナル
2018-03-17 15:58:111580ブラウズ

クラスのインターフェイスを顧客が望む別のインターフェイスに変換します。アダプター パターンを使用すると、互換性のないインターフェイスのために連携できないクラスが連携できるようになります。この記事では主にアダプターについて詳しく説明しますので、お役に立てれば幸いです。

メインの役割

ターゲットの役割: クライアントによって使用されるドメイン固有のインターフェースを定義します。これが私たちが期待するものです

ソースの役割: 適応する必要があるインターフェース

アダプターの役割: Adapte インターフェースは以下に適応しますターゲット インターフェイス。アダプターは、ソース インターフェイスをターゲット インターフェイスに変換します。この役割は、既存のクラスを使用する必要があります。ニーズを満たしていません

2. 他の無関係なクラスや予期しないクラスと連携できる再利用可能なクラスを作成したいと考えています

3. 既存のサブクラスが必要ですが、それぞれのインターフェイスに合わせてサブクラス化することはできません。オブジェクト アダプターはその親クラス インターフェイスに適応できます (オブジェクト アダプターのみ)

//目标角色  
interface Target {  
    public function simpleMethod1();  
    public function simpleMethod2();  
}  
  
//源角色  
class Adaptee {  
      
    public function simpleMethod1(){  
        echo &#39;Adapter simpleMethod1&#39;."<br>";  
    }  
}  
  
//类适配器角色  
class Adapter implements Target {  
    private $adaptee;  
      
      
    function __construct(Adaptee $adaptee) {  
        $this->adaptee = $adaptee;   
    }  
      
    //委派调用Adaptee的sampleMethod1方法  
    public function simpleMethod1(){  
        echo $this->adaptee->simpleMethod1();  
    }  
      
    public function simpleMethod2(){  
        echo &#39;Adapter simpleMethod2&#39;."<br>";     
    }   
      
}  
  
//客户端  
class Client {  
      
    public static function main() {  
        $adaptee = new Adaptee();  
        $adapter = new Adapter($adaptee);  
        $adapter->simpleMethod1();  
        $adapter->simpleMethod2();   
    }  
}  
  
Client::main();

おそらく、上記を踏まえてもアダプターが何であるかまだわからないでしょう。それでは次に詳しく説明していきます

アダプターモードはどんな時に使うの?

実際、最も簡単な例はサードパーティのライブラリを使用することです。これらのクラスライブラリはバージョンアップに伴いバージョンアップされ、対応するAPIも変更されます。インターフェイスが変わるとアダプターが役に立ちます

実際の例をご紹介します


最初は調和

Heizao Toy Companyはおもちゃの製造を専門とし、製造するおもちゃは犬、猫に限定されません、ライオン、魚、その他の動物。各おもちゃは「口を開ける」および「口を閉じる」操作を実行でき、それぞれ openMouth メソッドと closeMouth メソッドが呼び出されます。 現時点では、最初に抽象クラス Toy を定義すればよい、あるいはインターフェイス Toy を定義すればよいと考えるのは簡単です。これらの問題は、他のクラスが親クラスを継承して、親クラスのメソッドを実装することができます。調和と自信が生まれます。

スムーズな破壊


ビジネスを拡大するために、現在、Black Date Toy Company は、遠隔制御装置を使用して動物の口を制御できる Red Date Remote Control Company と協力しています。しかし、Hongzao Remote Control Company のリモート コントロール デバイスは、動物の doMouthOpen および doMouthClose メソッドを呼び出します。 Heizao Toy Company のプログラマーが今しなければならないことは、Toy が doMouthOpen メソッドと doMouthClose メソッドを呼び出せるように、Toy シリーズのクラスをアップグレードすることです。


実装方法を検討する際、必要に応じて、この 2 つのメソッドを親クラスとサブクラスに追加するだけでよいと直接考えました。この2つのメソッドを何度も親クラスとサブクラスに追加すると、必ずその繰り返しの作業を考えてしまいますが、解決できないでしょうか?何百ものサブクラスがあると、プログラマは気が狂ってしまうでしょう。プログラマーは、効率に影響を与えない場合に、誰がより「怠惰」であるかを競うことがよくあります。プログラマはこれを続けると愚かだと感じるでしょう。 (実際、私はよくこのバカみたいな行動をします)

りー

さらにイライラ

プログラマーがコーディングを終えて水を飲んだところ、突然別のニュースが届きました。 平竿玩具会社も陸竿遠隔制御会社と協力したいと考えています。陸竿遠隔制御会社の遠隔制御装置は安価で安定しているためです。しかし、Green Date Remote Control Company のリモート コントロール デバイスは、動物の operMouth(type) メソッドを呼び出して口の制御を実現します。 type が 0 の場合は「黙ってください」、それ以外の場合は口を開けてください。 ここで、プログラマは Toy とそのサブクラスをアップグレードして、Toy が operMouth() メソッドを呼び出せるようにする必要があります。もう誰も冷静ではありません。

abstract class Toy
{
    public abstract function openMouth();

    public abstract function closeMouth();

    //为红枣遥控公司控制接口增加doMouthOpen方法
    public abstract function doMouthOpen();

    //为红枣遥控公司控制接口增加doMouthClose方法
    public abstract function doMouthClose();
}

class Dog extends Toy
{
    public function openMouth()
    {
        echo "Dog open Mouth\n";
    }

    public function closeMouth()
    {
        echo "Dog open Mouth\n";
    }

    //增加的方法
    public function doMouthOpen()
    {
        $this->doMouthOpen();
    }

    //增加的方法
    public function doMouthClose()
    {
        $this->closeMouth();
    }
}

class Cat extends Toy
{
    public function openMouth()
    {
        echo "Cat open Mouth\n";
    }

    public function closeMouth()
    {
        echo "Cat open Mouth\n";
    }

    //增加的方法
    public function doMouthOpen()
    {
        $this->doMouthOpen();
    }

    //增加的方法
    public function doMouthClose()
    {
        $this->closeMouth();
    }
}

現時点では、プログラマは頭を使って解決策を考えなければなりません。たとえ熱心であっても、いつか紫の日付、緑の日付、黄色の日付、山の日付などのリモート制御会社が来たら、彼らは無視するでしょう。彼らのワークロードは増大しており、この Toy クラスはますます大きくなり、プログラマがクラッシュしなければ、いつかシステムがクラッシュするでしょう。

何が問題ですか?

上記のようにコードを書くと、コードの実装は「オープン-クローズ」原則に違反します。ソフトウェアエンティティは拡張に対してオープンであり、変更に対してクローズされる必要があります。つまり、モジュールを設計する際には、モジュールを変更せずに拡張する必要があります。言い換えれば、すべての死体は小さな王国です。私をあなたの業務に参加させることはできますが、私の内部コードが本当に最適化されない限り、私の内部コードを変更することはできません。 この考えにより、継承の使用方法、ポリモーフィズムの利用方法、さらには「高い凝集性と低い結合性」を実現する方法さえ理解できます。

 回到这个问题,我们现在面临这么一个问题,新的接口方法我要实现,旧的接口(Toy抽象类)也不能动,那么总得有个解决方法吧。那就是引入一个新的类--我们本文的主角--适配器。 适配器要完成的功能很明确,引用现有接口的方法实现新的接口的方法。更像它名字描述的那样,你的接口不改的话,我就利用现有接口和你对接一下吧。

到此,解决方法已经呼之欲出了,下面贴上代码。

<?php
abstract class Toy  
{  
    public abstract function openMouth();  
  
    public abstract function closeMouth();  
}  
  
class Dog extends Toy  
{  
    public function openMouth()  
    {  
        echo "Dog open Mouth\n";  
    }  
  
    public function closeMouth()  
    {  
        echo "Dog close Mouth\n";  
    }  
}  
  
class Cat extends Toy  
{  
    public function openMouth()  
    {  
        echo "Cat open Mouth\n";  
    }  
  
    public function closeMouth()  
    {  
        echo "Cat close Mouth\n";  
    }  
}


//目标角色:红枣遥控公司  
interface RedTarget  
{  
    public function doMouthOpen();  
  
    public function doMouthClose();  
}  
  
//目标角色:绿枣遥控公司及  
interface GreenTarget  
{  
    public function operateMouth($type = 0);  
}


//类适配器角色:红枣遥控公司  
class RedAdapter implements RedTarget  
{  
    private $adaptee;  
  
    function __construct(Toy $adaptee)  
    {  
        $this->adaptee = $adaptee;  
    }  
  
    //委派调用Adaptee的sampleMethod1方法  
    public function doMouthOpen()  
    {  
        $this->adaptee->openMouth();  
    }  
  
    public function doMouthClose()  
    {  
        $this->adaptee->closeMouth();  
    }  
}  
  
//类适配器角色:绿枣遥控公司  
class GreenAdapter implements GreenTarget  
{  
    private $adaptee;  
  
    function __construct(Toy $adaptee)  
    {  
        $this->adaptee = $adaptee;  
    }  
  
    //委派调用Adaptee:GreenTarget的operateMouth方法  
    public function operateMouth($type = 0)  
    {  
        if ($type) {  
            $this->adaptee->openMouth();  
        } else {  
            $this->adaptee->closeMouth();  
        }  
    }  
}



class testDriver  
{  
    public function run()  
    {  
         //实例化一只狗玩具  
        $adaptee_dog = new Dog();  
        echo "给狗套上红枣适配器\n";  
        $adapter_red = new RedAdapter($adaptee_dog);  
        //张嘴  
        $adapter_red->doMouthOpen();  
        //闭嘴  
        $adapter_red->doMouthClose();  
        echo "给狗套上绿枣适配器\n";  
        $adapter_green = new GreenAdapter($adaptee_dog);  
        //张嘴  
        $adapter_green->operateMouth(1);  
        //闭嘴  
        $adapter_green->operateMouth(0);  
    }  
}  
  
$test = new testDriver();  
$test->run();

更加烦躁
最后的结果就是,Toy类及其子类在不改变自身的情况下,通过适配器实现了不同的接口。

最后的总结

将一个类的接口转换成客户希望的另外一个接口,使用原本不兼容的而不能在一起工作的那些类可以在一起工作.

适配器模式核心思想:把对某些相似的类的操作转化为一个统一的“接口”(这里是比喻的说话)--适配器,或者比喻为一个“界面”,统一或屏蔽了那些类的细节。适配器模式还构造了一种“机制”,使“适配”的类可以很容易的增减,而不用修改与适配器交互的代码,符合“减少代码间耦合”的设计原则。

以上がPHPデザインパターンについて ~アダプターメソッドの詳細説明~の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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