今天我来全面总结一下Android开发中最常用的设计模式 - 适配器模式。
其他设计模式介绍
1分钟全面了解“设计模式”
单例模式(Singleton) - 最易懂的设计模式解析
简单工厂模式(SimpleFactoryPattern)- 最易懂的设计模式解析
工厂方法模式(Factory Method)- 最易懂的设计模式解析
抽象工厂模式(Abstract Factory)- 最易懂的设计模式解析
策略模式(Strategy Pattern)- 最易懂的设计模式解析
适配器模式(Adapter Pattern)- 最易懂的设计模式解析
代理模式(Proxy Pattern)- 最易懂的设计模式解析
模板方法模式(Template Method) - 最易懂的设计模式解析
建造者模式(Builder Pattern)- 最易懂的设计模式解析
外观模式(Facade Pattern) - 最易懂的设计模式解析
适配器模式,即定义一个包装类,用于包装不兼容接口的对象
包装类 = 适配器Adapter;
被包装对象 = 适配者Adaptee = 被适配的类
把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法一起工作的两个类能够在一起工作。
适配器模式的形式分为:类的适配器模式和对象的适配器模式
原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
类的适配器模式是把适配的类的API转换成为目标类的API。
2.1.1 UML类图 & 组成
Adapter与Adaptee是继承关系,这决定了这个适配器模式是类的
2.1.2 使用步骤(代码解析)
步骤1: 创建Target接口;
public interface Target {
//这是源类Adapteee没有的方法
public void Request();
}
步骤2: 创建源类(Adaptee) ;
public class Adaptee {
public void SpecificRequest(){
}
}
步骤3: 创建适配器类(Adapter)
//适配器Adapter继承自Adaptee,同时又实现了目标(Target)接口。
public class Adapter extends Adaptee implements Target {
//目标接口要求调用Request()这个方法名,但源类Adaptee没有方法Request()
//因此适配器补充上这个方法名
//但实际上Request()只是调用源类Adaptee的SpecificRequest()方法的内容
//所以适配器只是将SpecificRequest()方法作了一层封装,封装成Target可以调用的Request()而已
@Override
public void Request() {
this.SpecificRequest();
}
}
步骤4:定义具体使用目标类,并通过Adapter类调用所需要的方法从而实现目标
public class AdapterPattern {
public static void main(String[] args){
Target mAdapter = new Adapter();
mAdapter.Request();
}
}
2.1.3 实例讲解
接下来我用一个实例来对类的适配器模式进行更深一步的介绍。
a. 实例概况
即适配器模式中的类的适配器模式
b. 使用步骤
步骤1: 创建Target接口(期待得到的插头):能输出110V(将220V转换成110V)
public interface Target {
//将220V转换输出110V(原有插头(Adaptee)没有的)
public void Convert_110v();
}
步骤2: 创建源类(原有的插头) ;
class PowerPort220V{
//原有插头只能输出220V
public void Output_220v(){
}
}
步骤3:创建适配器类(Adapter)
class Adapter220V extends PowerPort220V implements Target{
//期待的插头要求调用Convert_110v(),但原有插头没有
//因此适配器补充上这个方法名
//但实际上Convert_110v()只是调用原有插头的Output_220v()方法的内容
//所以适配器只是将Output_220v()作了一层封装,封装成Target可以调用的Convert_110v()而已
@Override
public void Convert_110v(){
this.Output_220v;
}
}
步骤4:定义具体使用目标类,并通过Adapter类调用所需要的方法从而实现目标(不需要通过原有插头)
//进口机器类
class ImportedMachine {
@Override
public void Work() {
System.out.println("进口机器正常运行");
}
}
//通过Adapter类从而调用所需要的方法
public class AdapterPattern {
public static void main(String[] args){
Target mAdapter220V = new Adapter220V();
ImportedMachine mImportedMachine = new ImportedMachine();
//用户拿着进口机器插上适配器(调用Convert_110v()方法)
//再将适配器插上原有插头(Convert_110v()方法内部调用Output_220v()方法输出220V)
//适配器只是个外壳,对外提供110V,但本质还是220V进行供电
mAdapter220V.Convert_110v();
mImportedMachine.Work();
}
}
与类的适配器模式相同,对象的适配器模式也是把适配的类的API转换成为目标类的API。
与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用委派关系连接到Adaptee类。
2.2.1 UML类图
在上图中可以看出:
Adapter与Adaptee是委派关系,这决定了适配器模式是对象的。
2.2.2 使用步骤(代码解析)
步骤1: 创建Target接口;
public interface Target {
//这是源类Adapteee没有的方法
public void Request();
}
步骤2: 创建源类(Adaptee) ;
public class Adaptee {
public void SpecificRequest(){
}
}
步骤3: 创建适配器类(Adapter)(不适用继承而是委派)
class Adapter implements Target{
// 直接关联被适配类
private Adaptee adaptee;
// 可以通过构造函数传入具体需要适配的被适配类对象
public Adapter (Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void Request() {
// 这里是使用委托的方式完成特殊功能
this.adaptee.SpecificRequest();
}
}
步骤4:定义具体使用目标类,并通过Adapter类调用所需要的方法从而实现目标
public class AdapterPattern {
public static void main(String[] args){
//需要先创建一个被适配类的对象作为参数
Target mAdapter = new Adapter(new Adaptee());
mAdapter.Request();
}
}
在这里我就不再举实例进行讲解了(详情请看上面“进口机器的插头”),只是在适配类实现时将“继承”改成“在内部委派Adaptee类”而已
优点
缺点
优点
缺点
优点
缺点
特别是需要重新定义Adaptee行为时需要重新定义Adaptee的子类,并将适配器组合适配
灵活使用时:选择对象的适配器模式
类适配器使用对象继承的方式,是静态的定义方式;而对象适配器使用对象组合的方式,是动态组合的方式。
需要同时配源类和其子类:选择对象的适配器
建议尽量使用对象的适配器模式,多用合成/聚合、少用继承。
当然,具体问题具体分析,根据需要来选用合适的实现方式
相关文章阅读
单例模式(Singleton) - 最易懂的设计模式解析
简单工厂模式(SimpleFactoryPattern)- 最易懂的设计模式解析
工厂方法模式(Factory Method)- 最易懂的设计模式解析
抽象工厂模式(Abstract Factory)- 最易懂的设计模式解析
策略模式(Strategy Pattern)- 最易懂的设计模式解析
适配器模式(Adapter Pattern)- 最易懂的设计模式解析
代理模式(Proxy Pattern)- 最易懂的设计模式解析
模板方法模式(Template Method) - 最易懂的设计模式解析
建造者模式(Builder Pattern)- 最易懂的设计模式解析
外观模式(Facade Pattern) - 最易懂的设计模式解析