23种设计模式 之 适配器模式
概念
适配器(Adapter)模式,是将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
举例理解
1.你出国旅游,但是英文稀烂,这时候就需要一个翻译来解决燃眉之急。这个翻译员就是充当了适配器的角色,以使得说中文的你和说英文的当地人顺利交流。
2.手机充电,需要的是5V的电压,直接用220V的可不行。这时候就需要一个电源适配器来解决燃眉之急。这个适配器已经说的很直白了,将电源输入220V(适配者)转换为5V输出(目标)。
使用场景
客户端需要一个target(目标)接口,但是不能直接重用已经存在的adaptee(适配者)类,因为它的接口和target接口不一致,所以需要adapter(适配器)将adaptee转换为target接口。
前提是target接口和已存在的适配者adaptee类所做的事情是相同或相似,只是接口不同且都不易修改。
如果在设计之初,最好不要考虑这种设计模式。凡事都有例外,就是设计新系统的时候考虑使用第三方组件,因为我们就没必要为了迎合它修改自己的设计风格,可以尝试使用适配器模式。
角色
Target(目标角色):这是客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
Adapter(适配器角色):将已有接口转换成目标接口。
Adaptee(适配者角色):已有接口,但是和客户器期待的接口不兼容。
示例
以前的笔记本是支持网线接口的,后来因为诸多原因,比如笔记本越来越薄,就去除了网线接口。这时候如果想要插拔网线,就需要网线转换器了。
咱们来模拟实现这一过程~
1.0 此时笔记本支持网线接口
// 常用的网线接口 RJ-45,俗称“水晶头”
interface RJ45
{
public function request();
}
// 网线 (RJ-45接口标准的网线)
class Cable implements RJ45
{
public function request()
{
echo '网线连接正常,可以上网了!';
}
}
// 电脑
class Computer
{
// 上网
public function net(RJ45 $rj45)
{
$rj45->request();
}
}
// 实例化一根网线
$cable = new Cable;
// 实例化一个电脑
$compuser = new Computer;
// 电脑插上网线实现上网方法
$compuser->net($cable);
输出:
网线连接正常,可以上网了!
2.0 时代变迁,原来的水晶头接口不支持了,改用USB接口了。为了使用网线,只能借助网线适配器了
// 现在常用的USB接口
interface USB
{
// 这个方法名也可能不同
public function request();
}
// 微型电脑
class Microcomputer
{
// 上网 (仅支持USB接口,RJ45接口是不管用的)
public function net(USB $usb)
{
$usb->request();
}
}
// 网线适配器
class CableAdapter implements USB
{
protected $rj45;
// 适配的对象 RJ45接口
public function __construct(RJ45 $rj45) {
$this->rj45 = $rj45;
}
// 实现USB接口的方法
public function request()
{
// 实现RJ45接口的方法
$this->rj45->request();
}
}
// 实例化一台微型电脑
$microcomputer = new Microcomputer;
// 实例化一条网线
$cable = new Cable;
// 将网线插入网线适配器
$cable_adapter = new CableAdapter($cable);
// 将网线适配器插入电脑
$microcomputer->net($cable_adapter);
输出:
网线连接正常,可以上网了!
写在最后
适配器模式,是对已有接口的兼容,毕竟祖传代码动不得,甲方惹不起,只能退而求其次,想一个折中的法子了。
希望我把这个设计模式讲明白了。