深入浅出适配器模式
简介
在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。
对象适配器模式
在这种适配器模式中,适配器容纳一个它包裹的类的实例。在这种情况下,适配器调用被包裹对象的物理实体。
类适配器模式
这种适配器模式下,适配器继承自已实现的类(一般多重继承)
适配器模式思想:
适配器模式的宗旨:保留现有类所提供的服务,向客户提供接口,以满足客户的期望。
优点:
- 可以让任何两个没有关联的类一起运行。
- 提高了类的复用。
- 增加了类的透明度。
- 灵活性好。
缺点:
- 过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
- 由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
代码实例
描述:
定义一个插座接口MySocket,方法为doTake(插口类型,使用者名字),对插座类的扩展接口MySuperSocket,有具体的插口功能实现,如TypeA和TypeB的实现,适配器类MySocketAdapter对插座接口进行了实现,并依赖MySuperSocket可以不同的接口进行充电,UseMySocket为直接面向用户的类,依赖适配器类,可以对不同类型的接口进行适配,最高程度的满足用户的需求
类关系图:
代码:
public class Adapter { /** * 测试 * @param args */ public static void main(String[] args) { UseMySocket socket = new UseMySocket(); socket.doTake("A","张零"); socket.doTake("B","张一"); socket.doTake("C","张二"); socket.doTake("D","张三"); } } /** * 插座 */ interface MySocket { /** * 默认接口 */ void doTake(String type, String name); } interface MySuperSocket { /** * A型接口 */ void typeA(String name); /** * B型接口 */ void typeB(String name); } /** * B型插座类 */ class TypeBSocketer implements MySuperSocket { @Override public void typeA(String name) { //空实现 return; } @Override public void typeB(String name) { System.out.println(name + " Use TypeB"); } } /** * A型插座类 */ class TypeASocketer implements MySuperSocket { @Override public void typeA(String name) { System.out.println(name + " Use TypeA"); } @Override public void typeB(String name) { //空实现 return; } } /** * 适配器类 */ class MySocketAdapter implements MySocket { private MySuperSocket superSocket; public MySocketAdapter(String type) { if ("A".equals(type)) { superSocket = new TypeASocketer(); } else if ("B".equals(type)) { superSocket = new TypeBSocketer(); } } @Override public void doTake(String type, String name) { if ("A".equals(type)) { superSocket.typeA(name); } else if ("B".equals(type)) { superSocket.typeB(name); } } } /** * 直接面向用户的类 */ class UseMySocket implements MySocket { private MySocketAdapter mySocketAdapter; @Override public void doTake(String type, String name) { if ("C".equals(type)) { System.out.println(name+" Use TypeC"); } else if ("A".equals(type) || "B".equals(type)) { mySocketAdapter = new MySocketAdapter(type); mySocketAdapter.doTake(type, name); } else { System.out.println(name + " Not Find Type To Use"); } } }
测试结果:
public class Adapter { /** * 测试 * @param args */ public static void main(String[] args) { UseMySocket socket = new UseMySocket(); socket.doTake("A","张零"); socket.doTake("B","张一"); socket.doTake("C","张二"); socket.doTake("D","张三"); } }