适配器模式
适配器模式将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
Example: 指鹿为马
假设由鹿和马的类:
package com.gitlearning.hanldegit.patterns.adapter;
// 鹿
public class Deer {
void walk() ;
}
package com.gitlearning.hanldegit.patterns.adapter;
// 马
public interface Horse {
void run() ;
}
以及各自实现黑马和白鹿(话说《白鹿原》这本书还可以的,陈忠实先生的叙述引人入胜):
package com.gitlearning.hanldegit.patterns.adapter;
public class BlackHorse implements Horse {
@Override
public void run() {
System.err.println("黑马在跑");
}
}
package com.gitlearning.hanldegit.patterns.adapter;
public class WhiteDeer implements Deer {
@Override
public void walk() {
System.err.println("silence walk.");
}
}
看下鹿的适配器,
package com.gitlearning.hanldegit.patterns.adapter;
public class DeerAdapter implements Horse {
Deer deer;
public DeerAdapter(Deer deer) {
this.deer = deer;
}
@Override
public void run() {
deer.walk();
}
}
通过测试程序,来见证奇迹:
@Test
void test() {
Deer deer = new WhiteDeer();
Horse blackHorse = new BlackHorse();
DeerAdapter deerAdapter = new DeerAdapter(deer);
System.err.println(deer instanceof Deer);
System.err.println(blackHorse instanceof Horse);
System.err.println("白鹿是马吗?" + (deer instanceof Horse));
System.err.println("适配器是马吗?" + (deerAdapter instanceof Horse));
}
我们发现输出为:
true
true
白鹿是马吗?false
适配器是马吗?true
哈哈,如果当时赵高使用了DeerAdapter,当然可以说它就是马啦!
使用
并发包Executors有个静态内部类RunnableAdapter(对象适配器),成功的将Runnable转换成了Callable。在ThreadPoolExecutor调用submit(Runnable)的时候,内部默默的调用过RunnableAdapter将Runnable转为Callable。
这里还有一个FutureTask类实现了RunnableFuture接口,该接口分别继承了Runnable和Future接口,也是适配器的一种实现,不过是另一种实现,类适配器。
static final class RunnableAdapter implements Callable {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result;
}
}
其他
- 适配器将一个对象包装起来以改变其接口;装饰者模式将一个对象包装起来以增加新的行为和责任;外观将一群对象包装起来以简化其接口。
- 当需要一个现有的类而其接口并不符合你的需要时,就使用适配器
- 适配器的实现复杂度依据目标接口的大小与复杂度而定。
- 适配器两种形式:类适配器和对象适配器