简介
《设计模式》一书对于Adapter设计模式的意图的描述:
将一个类的接口转换成客户需要的另外一个接口。Adapter模式使原本由于接口不兼容而不能一起工作的类可以一起工作。
问题描述
客户要求实现圆,为此需要创建一个从Shape类中派生的Circle类,需要为其编写display、fill和undisplay方法。
此时有软件工程师已经编写了一个处理圆形的类,名为XXCircle,但他的方法命名与设计不符。
不能直接使用XXCircle,因为需要保持Shape类的多态行为,主要原因为:
- 名称和参数列表不同——XXCircle类中的方法名称和参数列表都和Shape类不同;
- 无法派生它——不但方法名称必须相同,这个类还必须从Shape类派生。
代码片段
因此,此处想办法适配:
- 创建一个新类,派生自Shape类,因此实现了Shape的接口,但不需要重写XXCircle;
- Circle包含XXCircle;
- Circle将发给自己的请求传给XXCircle对象。
class Circle extends Shape {
...
private XXCircle xxCircle;
...
public Circle(){
xxCircle = new XXcircle;
}
public void display() {
xxCircle.dispalyIt();
}
}
关键特征
意图 | 使控制范围之外的一个原有对象与某个接口匹配。 |
---|---|
问题 | 系统的数据和行为都正确,但接口不符。通常用于必须从抽象类派生时。 |
解决方案 | Adapter模式提供了具有所需接口的包装类。 |
参与者与协作者 | Adapter改变了Adaptee的接口,使Adaptee与Adapter的基类Target匹配。这样Client就可以使用Adaptee类,好像它是Target类型。 |
效果 | Adapter模式使原有对象能够适应新的类结构,不受其接口的限制。 |
实现 | 使原有类包含在另一个类之中。让包含类与需要的接口匹配,调用被包容类的方法。 |
Adapter设计模式的两种类型
对象Adapter
上述例子中使用的就是对象Adapter,因为它依赖于一个对象(适配对象)包含另一对象(被适配对象)。
// 适配器类,直接关联被适配类,同时实现标准接口
class Adapter implements Target{
// 直接关联被适配类
private Adaptee adaptee;
// 可以通过构造函数传入具体需要适配的被适配类对象
public Adapter (Adaptee adaptee) {
this.adaptee = adaptee;
}
public void request() {
// 这里是使用委托的方式完成特殊功能
this.adaptee.specificRequest();
}
}
// 测试类
public class Client {
public static void main(String[] args) {
// 使用普通功能类
Target concreteTarget = new ConcreteTarget();
concreteTarget.request();
// 使用特殊功能类,即适配类,
// 需要先创建一个被适配类的对象作为参数
Target adapter = new Adapter(new Adaptee());
adapter.request();
}
}
类Adapter
另一种实现Adapter模式的方式是通过多重继承。
类Adapter模式的工作原理是创建一个新类,该类同时从两个类继承:
- 从定义其接口的抽象类公开继承。
- 从访问其实现的原有类私有继承。
// 已存在的、具有特殊功能、但不符合我们既有的标准接口的类
class Adaptee {
public void specificRequest() {
System.out.println("被适配类 具有特殊功能...");
}
}
// 目标接口,或称为标准接口
interface Target {
public void request();
}
// 具体目标类,只提供普通功能
class ConcreteTarget implements Target {
public void request() {
System.out.println("普通类 具有普通功能...");
}
}
// 适配器类,继承了被适配类,同时实现标准接口
class Adapter extends Adaptee implements Target{
public void request() {
super.specificRequest();
}
}
// 测试类
public class Client {
public static void main(String[] args) {
// 使用普通功能类
Target concreteTarget = new ConcreteTarget();//实例化一个普通类
concreteTarget.request();
// 使用特殊功能类,即适配类
Target adapter = new Adapter();
adapter.request();
}
}
结论
将一个(或多个)类的接口转换成我们需要类所具备的一个接口。它的实现方式是:创建一个具备所需接口的类,然后包装原有类的方法,这样实际上就包含了被适配的对象。