PHP设计模式——适配器模式

  • 2019 年 11 月 24 日
  • 筆記

将类的接口转换为客户端期望的另一个接口。因为接口不兼容,无法一起工作,而适配器可以使类可以一起工作。

如今,全球共有15种电源插座插头在使用。从中国到新加坡旅行时,如果没有插座适配器,可能会遇到麻烦。前往新加坡参加研讨会的Marina非常沮丧,因为她意识到由于插头和插座不匹配,无法在酒店房间给手机和配件充电。她去了接待区,问旅馆工作人员是否有适配器。旅馆的工作人员很有礼貌,但是他们告诉她没有这种适配器,而Marina必须从当地的硬件那里购买一个。

在新加坡,使用的插座插头为G型,而来自中国的电子设备则使用A型插头。G型插座接口与A型插头不兼容,后者需要A型插座接口。在这种情况下,我们需要使用G型适配器来连接A型适配器。

这是适配器模式(Adapter Pattern)的示例。让我们看看它在代码中的样子。

首先,我们有一个TypeAPlug类和一个TypeGSocket类:

class TypeAPlug  {      public function connect(TypeASocketInterface $socket)      {          $socket->connectTwoPins();      }  }    class TypeGSocket  {      public function connectThreePins() {}  }

如我们所见,TypeAPlug类的connect()方法期望使用TypeASocketInterface类型,并调用TypeASocketInterface类型的方法connectTwoPins()。我们需要创建一个G型套接字接口来连接A型套接字接口适配器。我们将其命名为GtypeToAtypeSocketAdatper

class GtypeToAtypeSocketAdatper implements TypeASocketInterface  {      private $typeGSocket = null;      public function __construct(TypeGSocket $typeGSocket)      {          $this->typeGSocket = $typeGSocket;      }        public function connectTwoPins()      {          // 使用一些算法          $this->connectThreePins();      }  }

GtypeToAtypeSocketAdatper类实现TypeASocetInterface接口,并且在实例化时接受TypeGSocket类。此处使用的有利于合成的技术与“装饰器模式”中的类似。关键区别在于装饰器模式保留其包装的类的类类型。但是,适配器模式将其包装的类的类类型更改为一个客户端期望的类。

最后,让我们看看G型插座是如何转换为A型插座并由A型插头使用的:

$typeAPlug = new TypeAPlug();  $typeGSocket = new TypeGSocket();  $gTypeToAtypeAdapter = new GtypeToAtypeSocketAdatper($typeGSocket);  $typeAPlug->connect($gTypeToAtypeAdapter);

在适配器模式中,有一些组件可帮助您熟悉该模式,如下:

  • Adaptee:这是在引入适配器类之前存在的类。在我们的例子中,它将是TypeGSocket类。
  • Adapter:这是一个类,它包装一个Adaptee类并使其与客户端类所期望的兼容。此类将适配器类与客户端类分离。在我们的例子中,它是GtypeToAtypeSocketAdatper类。
  • Client:这是向适配器发出请求并接收其期望值的类。它不知道适配器类的存在。在我们的例子中,它是TypeAPlug类。

在我们的示例中,适配器模式(Adapter Pattern)将类(TypeGSockt类)的接口转换为客户端(TypeAPlug)期望的另一个接口(TypeAPlugInterface接口)。适配器(GtypeToAtypeSocketAdatper)允许类协同工作,否则由于接口不兼容而无法正常工作。