目录
- 什么是适配器模式
- 适用场景
- 适配器模式的三种实现方式
- 1. 类的适配器模式
- 2. 对象的适配器模式
- 3. 接口的适配器模式
- 总结
什么是适配器模式
适配器模式主要用于将一个类的接口转化成客户端希望的目标类格式,使得原本不兼容的类可以在一起工作,将目标类和适配者类解耦;同时也符合“开闭原则”,可以在不修改原代码的基础上增加新的适配器类;将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性,但是缺点在于更换适配器的实现过程比较复杂。
适用场景
-
将旧的接口适配成新的接口
在软件开发中,我们经常会遇到需要使用旧的类或组件,但它们的接口与我们期望的接口不兼容的情况。这时候,我们可以使用适配器模式将旧的接口适配成新的接口,使其能够协同工作。例如,Java中的InputStreamReader类就是一个适配器模式的应用,它将字节流转换成字符流,以便于读取文本文件。 -
将多个类的接口适配成统一的接口
在某些情况下,我们可能需要将多个类的接口适配成统一的接口,以便于我们能够使用它们的共同特性。例如,Java中的Enumeration接口定义了一组方法,可以遍历集合中的元素。但是,在Java 1.0中,集合类没有实现这个接口,而是使用了一个名为"elements"的方法。为了使集合类能够遵循Enumeration接口,Java提供了一个适配器类叫做"Iterator",它将"elements"方法适配成Enumeration接口的方法。 -
在不改变原有代码的情况下,增加新的功能
适配器模式还可以用于在不改变原有代码的情况下,增加新的功能。例如,如果我们想要给一个已经存在的类增加一些额外的功能,但是又不想修改这个类的代码,那么我们可以使用适配器模式来实现这个目的。具体的做法是,创建一个适配器类,将原有类的对象作为适配器类的成员变量,并在适配器类中添加新的方法。
适配器模式的三种实现方式
1. 类的适配器模式
- 目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
- 需要适配的类(Adaptee):需要适配的类或适配者类。
- 适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
完整代码
已存在的,但是拥有不符合我们要求接口的类
public class Adaptee {public void specificRequest() {System.out.println("被适配类具有 特殊功能...");}
}
目标接口,就是我们需要的统一接口
public interface Target {void request();
}
具体目标类,只提供普通功能,就是实现统一接口的普通类
public class ConcreteTarget implements Target{@Overridepublic void request() {System.out.println("我是普通类,实现普通功能");}
}
适配器类,继承了被适配类,同时实现标准接口
public class Adapter extends Adaptee implements Target{@Overridepublic void request() {super.specificRequest();}
}
测试
public class Client {public static void main(String[] args) {// 使用普通功能类Target concreteTarget = new ConcreteTarget();concreteTarget.request();// 使用特殊功能类,即适配类Target adapter = new Adapter();adapter.request();}
}
结果
2. 对象的适配器模式
class Adapter implements Target{// 直接关联被适配类private Adaptee adaptee;// 可以通过构造函数传入具体需要适配的被适配类对象public Adapter (Adaptee adaptee) {this.adaptee = adaptee;}public void request() {// 这里是使用委托的方式完成特殊功能this.adaptee.specificRequest();}
}// 测试类
public class Client {public static void main(String[] args) {// 使用普通功能类Target concreteTarget = new ConcreteTarget();concreteTarget.request();// 使用特殊功能类,即适配类,// 需要先创建一个被适配类的对象作为参数Target adapter = new Adapter(new Adaptee());adapter.request();}
}
测试结果与上面的一致。从类图中我们也知道需要修改的只不过就是 Adapter 类的内部结构,即 Adapter 自身必须先拥有一个被适配类的对象,再把具体的特殊功能委托给这个对象来实现。使用对象适配器模式,可以使得 Adapter 类(适配类)根据传入的 Adaptee 对象达到适配多个不同被适配类的功能,当然,此时我们可以为多个被适配类提取出一个接口或抽象类。这样看起来的话,似乎对象适配器模式更加灵活一点。
3. 接口的适配器模式
有时我们写的一个接口中有多个抽象方法,当我们写该接口的实现类时,必须实现该接口的所有方法,这明显有时比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这个问题,我们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行
public interface Sourceable {void method1();void method2();void method3();void method4();
}
public abstract class Wrapper implements Sourceable{@Overridepublic void method1() {}@Overridepublic void method2() {}@Overridepublic void method3() {}@Overridepublic void method4() {}
}
public class WrapperSub extends Wrapper{@Overridepublic void method1() {System.out.println("是我method1");}
}
public class WrapperSub1 extends Wrapper{@Overridepublic void method2() {System.out.println("我是method2");}
}
public class Client {public static void main(String[] args) {WrapperSub wrapperSub = new WrapperSub();wrapperSub.method1();WrapperSub1 wrapperSub1 = new WrapperSub1();wrapperSub1.method2();}
}
总结
适配器模式是一种非常常见的设计模式,它可以帮助我们解决不兼容的类或接口之间的问题,同时也可以帮助我们在不改变原有代码的情况下,增加新的功能。
参考:
https://blog.csdn.net/2302_77835532/article/details/130664014
https://blog.csdn.net/a745233700/article/details/83628122