设计模式之适配器模式
适配器模式将某各类的接口转换成客户端期望的另一个接口表示,目的是为了消除由于接口不匹配所造成的类的兼容性问题。
适配器模式涉及的角色有:
1.目标角色(target)
这是期望得到的接口。
2.源角色(Adaptee)
现在需要适配的接口。
3.适配器角色(Adapter)
适配器类,这是适配器模式的核心,负责把源接口转换为目标接口。
具体来说,适配器模式分为三类,分别是类的适配器模式、对象的适配器模式和接口的适配器模式。
下面一一介绍
一.类的适配器模式
类的适配器模式把适配的类的API转换为目标类的API
UML图如下:
示例代码如下:
1 public interface Target { 2 public void method1(); 3 public void method2(); 4 }
1 public class Adaptee { 2 3 public void method(){ 4 System.out.println("source method."); 5 } 6 7 }
下面是适配器模式的核心类Adapter:
1 public class Adapter extends Adaptee implements Target { 2 3 @Override 4 public void method1() { 5 //这样,待适配类的method()方法就适配成了目标类的method1() 6 super.method(); 7 } 8 9 @Override 10 public void method2() { 11 System.out.println("target method"); 12 } 13 14 }
下面是测试类:
1 public class AdapterTest { 2 public static void main(String[] args) { 3 Target adapter = new Adapter(); 4 adapter.method1(); 5 adapter.method2(); 6 } 7 }
测试结果如下:
二.对象的适配器模式
与类的适配器模式相比,对象的适配器模式不是使用多继承或继承再实现的方式,而是使用直接关联,或者称为委托的方式。
UML图如下:
从UML图可以看出与类的适配器模式相比,对象的适配器模式是在Adapter类中添加了一个对Adaptee的引用。使用对象适配器模式,可以使得 Adapter 类(适配类)根据传入的 Adaptee 对象达到适配多个不同被适配类的功能。
示例代码如下:
1 public interface Target { 2 public void method1(); 3 public void method2(); 4 }
1 public class Adaptee { 2 3 public void method(){ 4 System.out.println("source method."); 5 } 6 7 }
下面是对象的适配器模式的核心类Adapter:
1 public class Adapter implements Target { 2 private Adaptee adaptee; 3 4 public Adapter(Adaptee adaptee) { 5 this.adaptee = adaptee; 6 } 7 8 @Override 9 public void method1() { 10 adaptee.method(); 11 } 12 13 @Override 14 public void method2() { 15 System.out.println("target method"); 16 } 17 18 }
测试类如下:
1 public class AdapterTest { 2 public static void main(String[] args) { 3 Target adapter = new Adapter(new Adaptee()); 4 adapter.method1(); 5 adapter.method2(); 6 } 7 }
运行结果如下:
可以看出,输入的结果与类的适配器模式相同,只是适配的方式不同而已。
三.接口的适配器模式
接口的适配器模式是这样的:有时我们写的一个接口中有多个抽象方法,当我们写该接口的实现类时必须实现该接口的所有方法,这显然比较浪费,因为并不是所有的方法都是我们需要的,有时可能我们只需要某一些。为了解决这个问题,我们借助于一个抽象类,该抽象类实现了接口,实现了所有的方法,而我们不与原始的接口打交道,只和该抽象类有联系。这就是接口的适配器模式。
代码入下:
1 public interface Source { 2 public void method1(); 3 public void method2(); 4 }
1 //定义抽象类并实现Source接口的所有方法 2 public abstract class Wrapper implements Source{ 3 @Override 4 public void method1() {} 5 6 @Override 7 public void method2() {} 8 }
1 public class SourceSub1 extends Wrapper { 2 @Override 3 public void method1() { 4 System.out.println("the Source interface's first Sub1!"); 5 } 6 }
1 public class SourceSub2 extends Wrapper { 2 @Override 3 public void method2() { 4 System.out.println("the Source interface's first Sub2!"); 5 } 6 }
下面给出测试类:
1 public class SourceTest { 2 public static void main(String[] args) { 3 Source source1 = new SourceSub1(); 4 Source source2 = new SourceSub2(); 5 6 source1.method1(); 7 source1.method2(); 8 9 source2.method1(); 10 source2.method2(); 11 } 12 }
运行结果如下:
总结:
1.适配器模式的优点:
(1)更好的复用性
系统需要使用现有的类,而此类的接口不符合系统的需要,那么通过使用适配器模式可以使这些功能得到更好的复用。
(2)更好的扩展性
在实现适配器的功能时,可以调用自己开发的功能,从而扩展系统的功能。
2.适配器模式的缺点:
过多的使用适配器会让系统变得零乱,不易整体进行把握。例如,我们明明看到调用的是A的接口,然而内部却被适配成了B接口的调用,如果一个系统中出现太多这种情况,无异于一场灾难。因此,如果不是很有比较,不建议使用适配器模式,而是直接对系统进行重构。