【设计模式】适配器模式

时间:2022-07-03 21:58:45

1.定义

Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。

2.UML类图

【设计模式】适配器模式

分析:模式中的角色

  • 目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
  • 需要适配的类(Adaptee):需要适配的类或适配者类。
  • 适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。 

3.实现方式

(1)类的适配器模式(采用继承实现)

// 适配器类,继承了被适配类,同时实现标准接口 
class Adapter extends Adaptee implements Target{
public void request() {
super.specificRequest();
}
}

// 已存在的、具有特殊功能、但不符合我们既有的标准接口的类
class Adaptee {
public void specificRequest() {
System.out.println("被适配类具有 特殊功能...");
}
}

// 目标接口,或称为标准接口
interface Target {
public void request();
}

// 具体目标类,只提供普通功能
class ConcreteTarget implements Target {
public void request() {
System.out.println("普通类 具有 普通功能...");
}
}

// 测试类public class Client {
public static void main(String[] args) {
// 使用普通功能类
Target concreteTarget = new ConcreteTarget();
concreteTarget.request();

// 使用特殊功能类,即适配类
Target adapter = new Adapter();
adapter.request();
}
}

(2)对象适配器(采用对象组合方式实现)

//适配器类实现了目标接口
public class Adapter implements Target{
private Adaptee adaptee ;
public Adapter() {
super();
this.adaptee = new Adaptee();
}
@Override
public void getHeadset2() {
adaptee.getHeadset3();
}
public static void main(String args[]){
Target target = new Adapter();
//表面上调用的是2孔插座方法,但其实调用的三孔插座方法。
target.getHeadset2();
}
}
interface Target{
//两孔插座
void getHeadset2();
}
class Adaptee{
public void getHeadset3(){
System.out.println("我是三孔插座!");
}
}

4.适配器模式在JDK源码的使用

(1)Arrays.asList()源码如下

//类的适配器模式
public class Arrays {
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}

//省略很多行代码

private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{

ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
}

}

public class Objects {

//省略很多行代码

public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
Collections.list();
return obj;
}
}

分析:Arrays.asList()采用的是类的适配器模式,其中ArrayList是适配器,Arrays是目标类,而Objects是需要适配的类,Arrays并没有requireNonNull方法,而是通过适配器类ArrayList来实现该方法,而适配器ArrayList去找Objects.requireNonNull方法。

(2)InputStreamReader .read()源码如下

//对象适配器
public class InputStreamReader extends Reader{
private final StreamDecoder sd;

//省略很多行代码
public InputStreamReader(InputStream in) {
super(in);
try {
sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
} catch (UnsupportedEncodingException e) {
// The default encoding should always be available
throw new Error(e);
}
}

public int read() throws IOException {
return sd.read();
}
}

public class StreamDecoder {
//省略很多行代码
public int read() throws IOException {
return this.read0();
}

}

分析:InputStreamReader .read()采用的对象适配器模式,其中,InputStreamReader是适配器,StreamDecoder 是需要适配的类,Reader是目标类,实现Reader的read方法,调用的是InputStreamReader 的read方法,但最底层调用的是StreamDecoder 的read方法。



本人才疏学浅,若有错,请指出,谢谢!
如果你有更好的建议,可以留言我们一起讨论,共同进步!
衷心的感谢您能耐心的读完本篇博文!