定义
把一个类的接口变换成客户端所期望的另一个接口,从而使因接口不匹配而无法在一起工作的两个类能够一起工作。
分类
- 类适配器模式(使用继承的适配器)
- 对象适配器模式(使用委托的适配器)
使用场景
- 系统需要使用现有的类,但是类的接口不符合系统要求,即接口不兼容
- 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,或者说可能在将来引进的类一起工作
- 需要一个统一的输出接口,而输入端的类型不可知。
角色
- Target:目标角色。也就是所期待得到的接口。(类适配器模式下,此角色不可以是类)
- Adaptee:源角色。现在需要适配的接口。
- Adapter:适配器角色。核心。把源接口转换为目标接口。该角色必须为具体类。
将 Adaptee 的实现 包装成 Target 的实现 供 Client 调用
实现方式
此处不给示例代码。请参照 ListView 和 RecyclerView 的源码设计
类适配器模式
Adaptee
public class Banner {
private String content;
public Banner(String content) {
this.content = content;
}
public void showWithParen() {
System.out.println("(" + content + ")");
}
public void showWithAsterisk() {
System.out.println("*" + content + "*");
}
}
Target
public interface Print {
public abstract void printWeak(); // 弱化()
public abstract void printStrong(); // 强化 **
}
Adapter
public class PrintBanner extends Banner implements Print {
public PrintBanner(String content) {
super(content);
}
public void printWeak() {
showWithParen();
}
public void printStrong() {
showWithAsterisk();
}
}
测试
public class AdapterTest {
public static void main(String[] args) {
Print p = new PrintBanner("hello");
p.printWeak();
p.printStrong();
}
}
对象适配器模式
以上 Banner(Adaptee) 和 AdapterTest 的代码无需更改
Target
// 由于 Java 类不能多继承,只能单继承,所以 PrintBanner 无法同时继承 Print 和 Banner。
// 故只继承 Print(Target) 类,而【委托】Banner 来实现具体逻辑。
public abstract class Print {
public abstract void printWeak();
public abstract void printStrong();
}
Adapter
public class PrintBanner extends Print {
private Banner banner;
public PrintBanner(String content) {
banner = new Banner(content);
}
@Override
public void printWeak() {
// Target 的 printWeak() 方法【委托】banner 的 showWithParen() 实现
banner.showWithParen();
}
public void printStrong() {
// Target 的 printStrong() 方法【委托】banner 的 showWithAsterisk() 实现
banner.showWithAsterisk();
}
}
优缺点
优点
- 更好的复用性
- 更好的扩展性
缺点
- 过多使用适配器,会使系统非常凌乱,不易整体把握。
注意
版本升级与兼容性
可以通过 Adapter 模式使新旧版本兼容,帮助我们同时维护新版本和旧版本。
让新版本扮演 Adaptee(源) 角色,让旧版本扮演 Target(目标) 角色。再让新版本去实现旧版本的方法(Adaptee 通过 Adapter 来适配 Target),以此来达到新版本兼容旧版本的目的。
功能完全不同的类
当Adaptee 角色与 Target 角色的功能完全不同时,Adapter 模式是无法使用的。(就如同无法用 100V 交流电让自来水管出水一样)
建议
反复研读 ListView 和 RecyclerView 相关源码。
RecyclerView 与 ListView 的最大区别之一就是 将布局工作设置给了 LayoutManger,从而增强了系统的灵活性,降低了耦合度。可以灵活设置布局方式。
网友评论