ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。 >[danger]适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。 **该模式的主要优点如下。** * 客户端通过适配器可以透明地调用目标接口。 * 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。 * 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。 **其缺点是:** 对类适配器来说,更换适配器的实现过程比较复杂。 应用场景:老代码接口不适应新的接口需求,或者代码很多很乱不便于继续修改,或者使用第三方类库。 想使用一个已存在的类,但是该类不符合接口需求;或者需要创建一个可重用的类,适配没有提供合适接口的其它类。 一句话总结:不改变原有类的情况下对其进行改造 ## **①第一种方式:对象适配器** ~~~ //老的接口代码 class User { private $name; function __construct($name) { $this->name = $name; } public function getName() { return $this->name; } } //新代码,开放平台标准接口 interface UserInterface { function getUserName(); } class UserInfo implements UserInterface { protected $user; function __construct($user) { $this->user = $user; } public function getUserName() { return $this->user->getName(); } } $olduser = new User('张三'); echo $olduser->getName()."n";//张三n $newuser = new UserInfo($olduser); echo $newuser->getUserName()."n";//张三n ~~~ >[danger]**注意点**: 这里的新接口使用了组合方式,UserInfo内部有一个成员变量保存老接口User对象,模块之间是松耦合的,这种结构其实就是组合模式。不要使用继承,虽然UserInfo继承User也能达到同样的目的,但是耦合度高,相互产生影响。 新能源汽车的发动机有电能发动机(Electric Motor)和光能发动机(Optical Motor)等,各种发动机的驱动方法不同,例如,电能发动机的驱动方法 electricDrive() 是用电能驱动,而光能发动机的驱动方法 opticalDrive() 是用光能驱动,它们是适配器模式中被访问的适配者。 客户端希望用统一的发动机驱动方法 drive() 访问这两种发动机,所以必须定义一个统一的目标接口 Motor,然后再定义电能适配器(Electric Adapter)和光能适配器(Optical Adapter)去适配这两种发动机 ``` //目标:发动机 interface Motor { public function drive(); } //适配者1:电能发动机 class ElectricMotor { public function electricDrive() { echo "电能发动机驱动汽车!"; } } //适配者2:光能发动机 class OpticalMotor { public function opticalDrive() { echo "光能发动机驱动汽车!"; } } //电能适配器 class ElectricAdapter implements Motor { private $emotor; public function ElectricAdapter() { $this->emotor=new ElectricMotor(); } public function drive() { $this->emotor->electricDrive(); } } //光能适配器 class OpticalAdapter implements Motor { private $omotor; public function OpticalAdapter() { $this->omotor=new OpticalMotor(); } public function drive() { $this->omotor->opticalDrive(); } } //客户端代码 class MotorAdapterTest { public static function main($class) { echo "适配器模式测试:"; $motor=new $class(); $motor->drive(); } } MotorAdapterTest::main("ElectricAdapter"); MotorAdapterTest::main("OpticalAdapter"); ``` ## **②第二种方式:类适配器** ![](https://img.kancloud.cn/56/ab/56abbf41f2d0aa10ab9b9340857e0d9b_639x326.png) ``` //目标接口 interface Target { public function request(); } //适配者接口 class Adaptee { public function specificRequest() { echo "适配者中的业务代码被调用!"; } } //类适配器类 class ClassAdapter extends Adaptee implements Target { public function request() { $this->specificRequest(); } } //客户端代码 class ClassAdapterTest { public static function main() { echo "类适配器模式测试:"; $target = new ClassAdapter(); $target->request(); } } ClassAdapterTest::main(); ``` ~~~ interface Target2 { public function sampleMethod1(); public function sampleMethod2(); } class Adaptee1 { // 源角色 public function sampleMethod1() {echo '++++++++';} } class Adapter2 extends Adaptee1 implements Target2 { // 适配后角色 public function sampleMethod2() {echo '————————';} } $adapter = new Adapter2(); $adapter->sampleMethod1();//输出:++++++++ $adapter->sampleMethod2();//输出:———————— ~~~ ## **模式的扩展**:双向适配器模式 双向适配器类既可以把适配者接口转换成目标接口,也可以把目标接口转换成适配者接口 ![](https://img.kancloud.cn/8c/58/8c5862955e4082b51a4a8d4a5a87bceb_499x608.png) ``` //目标接口 interface TwoWayTarget { public function request(); } //适配者接口 interface TwoWayAdaptee { public function specificRequest(); } //目标实现 class TargetRealize implements TwoWayTarget { public function request() { echo "目标代码被调用!"; } } //适配者实现 class AdapteeRealize implements TwoWayAdaptee { public function specificRequest() { echo "适配者代码被调用!"; } } //双向适配器 class TwoWayAdapter implements TwoWayTarget,TwoWayAdaptee { private $target; private $adaptee; public function __construct($class){ if ($class instanceof TwoWayTarget) { $this->target=$class; } if ($class instanceof TwoWayAdaptee) { $this->adaptee=$class; } } public function request() { $this->adaptee->specificRequest(); } public function specificRequest() { $this->target->request(); } } //客户端代码 class TwoWayAdapterTest { public static function main() { echo "目标通过双向适配器访问适配者:"; $adaptee=new AdapteeRealize(); $target=new TwoWayAdapter($adaptee); $target->request(); echo "-------------------"; echo "适配者通过双向适配器访问目标:"; $target=new TargetRealize(); $adaptee=new TwoWayAdapter($target); $adaptee->specificRequest(); } } TwoWayAdapterTest::main(); ```