适配器模式 - Adapter Pattern
定义
将一个接口转换成客户所期望的另一个接口,使接口不兼容的那些类可以一起工作。
设计的原则和思想
- 解耦的是目标类(适配器类)和适配者类。
- 不变部分是适配者,变化部分是适配器。
- 核心思想是将类中原本不兼容的接口转换成兼容的接口。是一种事后的补救策略。
一句话概括设计模式
将接口转换成另一个接口,消除不兼容问题。
适配器模式分三种
- 类适配器
- 对象适配器
- 接口适配器模式(缺省适配器模式)
类适配器和对象适配器
结构中包含的角色
- Target(目标抽象类)
- Adapter(适配器类)
- Adaptee(适配者类)
最小可表达代码
// 目标抽象类
interface Target
{
public function outputA();
}
// 适配者类
class Adaptee
{
public function outputB(){}
}
// 类适配器
class ClassAdapter extends Adaptee implements Target
{
public function outputA()
{
echo '类适配器的业务处理';
}
}
// 对象适配器
class ObjectAdapter implements Target
{
private $adaptee;
public function __construct(Adaptee $adaptee)
{
$this->adaptee = $adaptee;
}
public function outputA()
{
echo '对象适配器的业务处理';
}
}
(new ClassAdapter())->outputA();
(new ObjectAdapter(new Adaptee))->outputA();
接口适配器模式(缺省适配器模式)
结构中包含的角色
- Target(目标抽象类)
- DefaultAdapter(默认适配器类)
- ConcreteAdapter(具体适配器类)
最小可表达代码
interface Target
{
public function outputA();
public function outputB();
}
abstract class DefaultAdapter implements Target
{
public function outputA(){}
public function outputB(){}
}
class ConcreteAdapter extends DefaultAdapter
{
public function outputA()
{
echo '接口适配器的业务处理';
}
}
(new ConcreteAdapter())->outputA();
优点
- 可以让任何两个没有关联的类一起运行。
- 可以将接口或数据转换代码从程序主要业务逻辑中分离。
- 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构。
缺点
- 过多地使用适配器,会让系统非常零乱,不易整体进行把握。
- 代码整体复杂度增加。
何时使用
- 封装有缺陷的接口设计
- 统一多个类的接口设计
- 通过接口转换,将一个类插入另一个类系中。
- 兼容老版本接口
- 适配不同格式的数据
- 系统需要使用现有的类,而此类的接口不符合系统的需要。
实际应用场景
- 美国电器 110V,中国 220V,就要有一个适配器将 110V 转化为 220V。
- 在 LINUX 上运行 WINDOWS 程序。
类适配器和对象适配器
类适配器
这一实现使用了继承机制 : 适配器同时继承两个对象的接口。请注意,这种方式仅能在支持多重继承的编程语言中实现,例如 C++。
对象适配器
实现时使用了构成原则 : 适配器实现了其中一个对象的接口, 并对另一个对象进行封装。 所有流行的编程语言都可以实现适配器。