适配器主要用于接口的转换或者将接口不兼容的类对象组合在一块儿造成对外统一接口,是一种结构性模式,其本质是是一个中间件,适用于类及其对象。
本文但愿经过简单的介绍和分析,能让读者对适配器模式有一个简单直观的认识和感知。html
对现有的类的接口进行转换以符合新的需求。编程
经过转换或者组合,间接复用已有功能模块完成需求。数据结构
优势:ide
缺点:spa
本文主要介绍前二者。设计
该模式并非在设计开发阶段考虑的,主要用在想要修改一个已经存在的接口,或者组合若干关联对象的时候。代理
下面是GoF介绍的典型的类适配器模式和对象适配器模式的UML类图code
类适配器htm
原理:经过类继承实现适配,继承Target的接口,继承Adaptee的实现中间件
对象适配器
原理:经过类对象组合实现适配
Target:
定义Client真正须要使用的接口。
Adaptee:
其中定义了一个已经存在的接口,也是咱们须要进行适配的接口。
Adapter:
对Adaptee和Target的接口进行适配,保证对target中接口的调用能够间接转换为对Adaptee中接口进行调用。
接下来先将上面的UML类图转换为两个具体的例子,而后在对每一种类型在使用一个具体例子介绍.
下面咱们使用几个例子来实际体验一下代理模式的应用。
定义目标接口类:Target
public interface Target { void request(); }
被适配的类:Adaptee
public class Adaptee { public void adapteeRequest() { System.out.println("adapteeRequest method of Adaptee! "); } }
适配类Adapter,继承Target的接口request,同时继承Adaptee的实现adapteeRequest
public class Adapter extends Adaptee implements Target { @Override public void request() { // TODO Auto-generated method stub super.adapteeRequest(); } }
演示:
public class Demo { public static void main(String [] args) { Target target = new Adapter(); target.request(); // result: adapteeRequest method of Adaptee! } }
从上面两张UML图中能够清楚的看出二者的区别,对象中Adapter不在继承Adaptee,而是将Adaptee做为一个数据成员组合到类定义中,从而实现对其接口的访问。
public class Adapter implements Target { private Adaptee adaptee = new Adaptee(); @Override public void request() { // TODO Auto-generated method stub adaptee.adapteeRequest(); } }
考虑到某系统中有对数据排序的需求,下面使用适配器看一下如何复用现有的排序接口(下面的例子仅仅为了演示,接口不具实际意义);
现有排序类:EffectiveVectorSort
public class EffectVectorSort { public void vectorSort() { System.out.println("vectorSort method of EffectVectorSort! "); } }
系统排序所需的接口类定义:DataSort
public interface DataSort { void sort(); }
定义适配器:SortAdapter
public class SortAdapter extends EffectVectorSort implements DataSort { @Override public void sort() { // TODO Auto-generated method stub super.vectorSort(); } }
演示:
public class Demo { public static void main(String [] args) { DataSort dataSort = new SortAdapter(); dataSort.sort(); // vectorSort method of EffectVectorSort! } }
若是系统中不只有对向量Vector的排序,也有对元组Tuple和链表LinkList等高级数据结构的排序,那么显然经过没法经过类适配将每个排序类的子类都继承。这里即可以用到对象适配。
须要修改7.3中的SortAdapter,同时须要定义高级数据结构的排序类。
高级数据结构排序类接口:AdvanceDataSort
public interface AdvanceDataSort { void sort(); }
链表排序类:LinkListSort
public class LinkListSort implements AdvanceDataSort { @Override public void sort() { // TODO Auto-generated method stub System.out.println("sort method of LinkListSort!"); } }
元组排序类:TupleSort
public class TupleSort implements AdvanceDataSort { @Override public void sort() { // TODO Auto-generated method stub System.out.println("sort method of TupleSort"); } }
重定义适配器:SortAdapter
public class SortAdapter implements DataSort { private EffectVectorSort vectorSort = new EffectVectorSort(); private AdvanceDataSort listSort = new LinkListSort(); private AdvanceDataSort tupleSort = new TupleSort(); @Override public void sort(String dataType) { // TODO Auto-generated method stub if(dataType == "vector") { vectorSort.vectorSort(); } else if(dataType == "linklist") { listSort.sort(); } else if(dataType == "tuple") { tupleSort.sort(); } else { System.out.println("Invalid Data Type:" + dataType); } } }
演示:
public class Demo { public static void main(String [] args) { DataSort dataSort = new SortAdapter(); dataSort.sort("vector"); // vectorSort method of EffectVectorSort! dataSort.sort("linklist"); // sort method of LinkListSort! dataSort.sort("tuple"); // sort method of TupleSort dataSort.sort("dict"); // Invalid Data Type:dict } }
限于篇幅,先介绍到这里。上面的例子都是比较直观,简单的。好好体会,将其应用到实际编程中才是咱们的目的。
参考:
GoF《Design Patterns: Elements of Reusable Object-Oriented Software》
https://www.runoob.com/design-pattern/adapter-pattern.html