一、Adapter模式
适配器模式将一个类的接口,转换成客户期望的另一个接口,适配器让原本接口不兼容的类可以合作无间。
生活中的例子就是,如果想让12V的笔记本电脑在220V的交流电下工作的话,就需要在中间增加一个适配器。
适配器模式有两种:
- 类适配器模式(使用继承实现的)
- 对象适配器模式(使用委托实现的)
后面会分别介绍这两种
二、示例程序
使用继承模式的适配器类图
Banner类
- public class Banner {
- private String string;
- public Banner(String string) {
- this.string = string;
- }
- public void showWithParen() {
- System.out.println("(" + string + ")");
- }
- public void showWithAster() {
- System.out.println("*" + string + "*");
- }
- }
PrintBanner实现Print接口并继承Banner类
public class PrintBanner extends Banner implements Print {
public PrintBanner(String string){
super(string);
}
@Override
public void printWeak() {
showWithParen();
}
@Override
public void printStrong() {
showWithAster();
}
}
被客户端调用的print接口定义了有哪些方法
public interface Print {
void printWeak();
void printStrong();
}
测试类Main
public class Main {
public static void main(String[] args) {
Print p = new PrintBanner("Hello");
p.printWeak();
p.printStrong();
}
}
运行结果如下:
(Hello)
*Hello*
Main类并不知道PrintBanner类是如何实现的,这样就可以不用对Main类修改的前提下改变PrintBanner类的具体实现,这里其实是交给了Banner类去实现。
使用委托模式的适配器
跟之前相比,只需要改变PrintBanner类的代码,其他类不需要修改。
public class PrintBanner implements Print {
private Banner banner;
public PrintBanner(String string){
banner = new Banner(string);
}
@Override
public void printWeak() {
banner.showWithParen();
}
@Override
public void printStrong() {
banner.showWithAster();
}
}
可以看出,这里通过PrintBanner的构造方法来创建委托对象banner,方法的实际处理其实是交给了banner对象去执行。
Main类的运行结果是一样的,省略。
Adapter模式有四种角色:
Target(对象)
该角色负责定义所需的方法,即示例中的Print接口。
Client(请求者)
该角色负责使用Targer的方法,即示例中的Main类。
Adaptee(被适配)
Adaptee是一个持有特定方法的角色,如果Adaptee角色的方法与Target角色的方法相同,那么就不需要Adapter了,即示例中的Banner类。
Adapter(适配)
即示例中的PrintBanner类。
三、使用场景
既然适配器模式这么好用,那么什么时候需要使用它呢?
1.开发时复用现有的并且已经经过测试的类
2.版本升级与兼容
外观,装饰者,适配器三种模式很容易混淆,可以这样区分。
装饰者:不改变接口,但加入责任(新功能)。
适配器:将一个接口转成另一个接口。
外观:让接口更简单。