一、概念
1、定义:将一个类的接口转换成客户期望的另一个接口,让原本接口不兼容的类兼容
2、类型:结构型
3、适用环境
- 已经存在的类,它的方法和需求不匹配时(比如我们想要复用一些现有的类,它只是接口不符合,就可以用适配器模式)
- 不是软件设计阶段去考虑的设计模式,而是随着软件维护,不同产品、不同厂家造成功能类似而接口不同情况下的解决方案。
4、优缺点
优点
- 把目标类和适配者类解耦,提高扩展性
- 符合OCP,可以在原有代码基础上增加新的适配器
- 具体的实现封装在适配者类中,对于客户端类来说是透明的(就是客户端感受不到)
缺点
- 适配器在编写时要全面考虑,会增加系统复杂性
- 增加代码可读难度,接口调接口,读起来困难
5、两种适配器
- 对象适配器
- 符合组合复用原则,使用委托机制(优先使用组合而不是继承)
- 符合组合复用原则,使用委托机制(优先使用组合而不是继承)
- 类适配器
- 通过类继承来实现
- 通过类继承来实现
6、相关设计模式
-
适配器和装饰者模式
意图不一样,适配器是将一个类的接口转换成客户期望的接口,而装饰者是给被装饰者动态的增加职责,用于扩展功能。
-
适配器和外观模式
外观模式是定义一个新的接口,适配器是复用原有的接口;适配器使两个已有的接口协同工作,外观是提供更为方便的访问入口。
二、Coding
类适配器,通过继承实现
// 被适配者
public class Adaptee {
public void adapteeRequest(){
System.out.println("被适配者的方法");
}
}
// 目标
public interface Target {
void request();
}
public class ConcreteTarget implements Target {
@Override
public void request() {
System.out.println("concreteTarget目标方法");
}
}
// 适配者 通过 适配 被适配者 达到target目标
public class Adapter extends Adaptee implements Target{
@Override
public void request() {
// 通过Adapter,把被适配者的方法 适配给了Target
super.adapteeRequest();
//...
}
}
//Test
public class Test {
public static void main(String[] args) {
Target target = new ConcreteTarget();
target.request();
Target adapterTarget = new Adapter();
//实现通过Adapter来实现
adapterTarget.request();
}
}
//concreteTarget目标方法
//被适配者的方法
对象适配器,通过组合实现
// 被适配者
public class Adaptee {
public void adapteeRequest(){
System.out.println("被适配者的方法");
}
}
// 目标
public interface Target {
void request();
}
public class ConcreteTarget implements Target {
@Override
public void request() {
System.out.println("concreteTarget目标方法");
}
}
// 适配者,直接实现Target
public class Adapter implements Target {
//没有继承,无法调用父类方法,要把Adaptee组合过来,再调用
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
// 把具体实现Target的request方法委托给Adaptee来实现
// ...
adaptee.adapteeRequest();
// ...
}
}
三、双向适配器
设计和实现一个双向适配器实例,使得猫Cat可以学狗Dog叫Cry() ,狗可以学猫抓老鼠CatchMouse()
public interface Cat {
void catchMouse();
}
public class ConcreteCat implements Cat {
@Override
public void catchMouse() {
System.out.println("捉老鼠...");
}
}
public interface Dog {
void bark();
}
public class ConcreteDog implements Dog {
@Override
public void bark() {
System.out.println("汪汪汪...");
}
}
public class Adapter implements Cat,Dog{
private ConcreteCat concreteCat;
private ConcreteDog concreteDog;
public Adapter(ConcreteCat concreteCat) {
this.concreteCat = concreteCat;
}
public Adapter(ConcreteDog concreteDog) {
this.concreteDog = concreteDog;
}
@Override
public void catchMouse() {
concreteDog.bark();
}
@Override
public void bark() {
concreteCat.catchMouse();
}
}
public class Test {
public static void main(String[] args) {
Cat cat = new Adapter(new ConcreteDog());
cat.catchMouse();
Dog dog = new Adapter(new ConcreteCat());
dog.bark();
}
}