>  기사  >  백엔드 개발  >  PHP 디자인 패턴에 대하여 - 어댑터 방식에 대한 자세한 설명

PHP 디자인 패턴에 대하여 - 어댑터 방식에 대한 자세한 설명

零到壹度
零到壹度원래의
2018-03-17 15:58:111618검색

클래스의 인터페이스를 고객이 원하는 다른 인터페이스로 변환합니다. 어댑터 패턴을 사용하면 원래 인터페이스가 호환되지 않아 함께 작동할 수 없었던 클래스도 함께 작동할 수 있습니다. 이 기사에서는 주로 어댑터에 대한 자세한 설명을 공유하여 도움이 되기를 바랍니다.

주 역할

대상 역할: 클라이언트가 사용하는 도메인별 인터페이스를 정의합니다. 이것이 우리가 기대하는 것입니다.

소스 역할: 조정이 필요한 인터페이스

어댑터 역할: Adaptee 인터페이스는 다음에 적응합니다. 대상 인터페이스는 이 모델의 핵심입니다. 어댑터는 소스 인터페이스를 대상 인터페이스로 변환합니다. 이 역할은 기존 클래스를 사용하려는 경우 해당 인터페이스가 수행합니다. 요구 사항을 충족하지 못합니다.

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도 변경됩니다. 인터페이스가 바뀌면 어댑터가 유용합니다

실용적인 예를 들어보겠습니다


처음에는 조화

헤이자오토이컴퍼니는 장난감 제작을 전문으로 하고 있으며, 제작하는 장난감은 개, 고양이에 국한되지 않습니다. , 사자, 물고기 및 기타 동물. 각 장난감은 "입 열기" 및 "입 닫기" 작업을 수행할 수 있으며 openMouth 및 closeMouth 메서드가 각각 호출됩니다. 이때 추상 클래스인 Toy를 정의하거나 심지어 Toy라는 인터페이스를 먼저 정의하면 된다고 생각하기 쉽습니다. 이러한 문제는 크지 않습니다. 다른 클래스가 상위 클래스를 상속받아 상위 클래스의 메소드를 구현할 수도 있습니다. 조화와 자신감이 있습니다.

원활한 파괴


사업 확장을 위해 이제 블랙데이트토이컴퍼니는 원격제어 장치를 이용해 동물의 입을 제어할 수 있는 레드데이트 리모콘컴퍼니와 협력하게 되었습니다. 그러나 Hongzao Remote Control Company의 원격 제어 장치는 동물의 doMouthOpen 및 doMouthClose 메소드를 호출합니다. Heizao Toy Company의 프로그래머가 지금 해야 할 일은 Toy가 doMouthOpen 및 doMouthClose 메소드를 호출할 수 있도록 Toy 시리즈 클래스를 업그레이드하는 것입니다.


구현 방법을 고려할 때 필요하다면 이 두 가지 방법을 상위 클래스와 하위 클래스에 추가하면 된다고 직접 생각했습니다. 부모 클래스와 하위 클래스에 이 두 가지 메소드를 계속해서 추가하다 보면 이런 반복적인 작업이 늘 고민이 되실텐데요, 해결이 안될까요? 수백 개의 하위 클래스가 있으면 프로그래머는 미칠 것입니다. 프로그래머는 효율성에 영향을 미치지 않으면서 누가 더 "게으른"지 확인하기 위해 경쟁하는 경우가 많습니다. 프로그래머들이 이런 일을 계속한다면 바보처럼 느껴질 것입니다. (사실 제가 이런 바보 같은 짓을 자주 합니다)

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();
    }
}

더 짜증나

프로그래머가 막 코딩을 마치고 물을 마시고 있는데 갑자기 또 다른 소식이 들려왔습니다. Heizao Toy Company는 Luzao Remote Control Company의 원격 제어 장비가 더 저렴하고 안정적이기 때문에 Luzao Remote Control Company와 협력하기를 원합니다. 그러나 그린데이트리모컨컴퍼니의 원격제어 장치는 입 제어를 구현하기 위해 동물의 operMouth(type) 메소드를 호출한다. 유형이 0이면 "닥쳐", 그렇지 않으면 입을 벌립니다. 이제 프로그래머는 Toy가 operMouth() 메서드를 호출할 수 있도록 Toy와 해당 하위 클래스를 업그레이드해야 합니다. 더 이상 아무도 침착하지 않습니다.

abstract class Toy  
{  
    public abstract function openMouth();  
  
    public abstract function closeMouth();  
  
    public abstract function doMouthOpen();  
  
    public abstract function doMouthClose();  
  
    //为绿枣遥控公司控制接口增加doMouthClose方法  
    public abstract function operateMouth($type = 0);  
}  
  
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();  
    }  
  
    public function operateMouth($type = 0)  
    {  
        if ($type == 0) {  
            $this->closeMouth();  
        } else {  
            $this->operateMouth();  
        }  
    }  
}  
  
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();  
    }  
  
    public function operateMouth($type = 0)  
    {  
        if ($type == 0) {  
            $this->closeMouth();  
        } else {  
            $this->operateMouth();  
        }  
    }  
}

이때 프로그래머들은 머리를 써서 해결책을 생각해내야 합니다. 아무리 열심히 노력해도 어느 날 보라색대추, 초록대추, 노랑대추, 산대추 등 원격제어업체가 다 오면 무시할 겁니다. 작업량이 증가함에 따라 이 장난감 클래스는 점점 더 커지고 있으며 프로그래머가 충돌하지 않으면 언젠가는 시스템이 충돌할 것입니다.

무엇이 문제인가요?

위와 같이 코드를 작성하면 코드 구현이 "개방-폐쇄" 원칙을 위반하므로 소프트웨어 엔터티는 확장을 위해 개방되고 수정을 위해 폐쇄되어야 합니다. 즉, 모듈을 설계할 때 모듈을 수정하지 않고 확장해야 한다. 즉, 모든 시체는 작은 왕국입니다. 당신은 내가 당신의 일에 참여하게 할 수 있지만 내 내부 코드가 실제로 최적화되지 않으면 내 내부 코드를 수정할 수 없습니다. 이 아이디어를 통해 우리는 상속을 사용하는 방법, 다형성을 활용하는 방법, 심지어 "높은 응집력, 낮은 결합도"를 달성하는 방법까지 이해합니다.

 回到这个问题,我们现在面临这么一个问题,新的接口方法我要实现,旧的接口(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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.