适配器模式
适配器模式就是把一个类的接口转换成客户端所期待的另外一种接口,从而使原接口不匹配而无法在一起工作的的两个类能在一起工作。从功能上说,这些接口不兼容的类一般具有相同或相似的功能。通常我们通过修改该类的接口来解决这种接口不兼容的情形,但是如果我们不愿意为了一个应用而修改各原接口,或者我们压根儿就没有对象的源代码的时候,适配器模式就会派上用场了。
适配器的优点:
1、将目标类和适配者类解耦
2、增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性
3、灵活性和扩展性都非常好,符合开闭原则
适配器所涉及的角色包括下面几种:
目标(Target):定义一个客户端使用的特定接口。
客户端(Client):使用目标接口,与和目标接口一致的对象合作。
被适配者(Adaptee):一个现存需要适配的接口。
适配器(Adapter):负责将Adaptee的接口转换为Target的接口。适配器是一个具体的类,这是该模式的核心。
适配器分为类适配器和对象适配器两种,下面将详细讲述。
类适配器
所谓类适配器,指的是适配器Adapter继承我们的被适配者Adaptee,并实现目标接口Target。由于Java中是单继承,所以这个适配器仅仅只能服务于所继承的被适配者Adaptee。代码如下:
被适配者(Adaptee)
1 package com.bluemsun.classadapter; 2 3 public class Person { 4 private int id; 5 private String name; 6 /** 7 * person可以现在只能说英语 8 */ 9 public void sayEnglish(){ 10 System.out.println("Person can say english!"); 11 } 12 13 /** 14 * 省略setter,getter. 15 */ 16 }
目标接口(Target)
1 package com.bluemsun.classadapter; 2 3 /** 4 * 目标要求person可以说英语,法语,日语.但是现在的person仅仅可以说英语 5 * @author Administrator 6 * 7 */ 8 public interface Target_Person { 9 void sayEnglish(); 10 void sayFrench(); 11 void sayJapanese(); 12 }
适配器(Adapter)
1 package com.bluemsun.classadapter; 2 3 /** 4 * 类适配器,因为继承了Person,而Java中只能单继承,所以这个适配器只为person这一个类服务 5 * 这个适配器就让person类在不修改源码的基础上能实现目标接口所指定的方法 6 * @author Administrator 7 * 8 */ 9 public class Adapter_Person extends Person implements Target_Person{ 10 11 @Override 12 public void sayFrench() { 13 System.out.println("Person can say French!"); 14 } 15 16 @Override 17 public void sayJapanese() { 18 System.out.println("Person can say Japanese!"); 19 } 20 }
客户端(Client)
1 package com.bluemsun.classadapter; 2 3 public class Test { 4 public static void main(String[] args) { 5 Target_Person person = new Adapter_Person(); 6 7 person.sayEnglish(); 8 person.sayFrench(); 9 person.sayJapanese(); 10 } 11 }
上面的几段简单代码演示了类适配器的作用。正如我们开始所言,这个适配器Adapter只能为Person这一个类所服务。这时候你可能会想,要是我所需要适配的类很多,是不是都需要为每一个需要适配的类写一个Adapter?有没有更加灵活的方式呢?答案是:有!就是我们下面所讲的对象适配器。
对象适配器
所谓对象适配器,简单的说就是适配器实现我们的目标接口,但是并不继承需要被适配的类。而是通过在适配器的构造函数中将需要被适配的类传递进来从而进行适配。代码如下:(Target,Adaptee同上)
适配器(Adapter)
1 package com.bluemsun.objectdapter; 2 3 import com.bluemsun.classadapter.Person; 4 import com.bluemsun.classadapter.Target_Person; 5 6 /** 7 * 对象适配器,与类适配器不同的是:对象适配器可以适配多个源到目标 8 * @author Administrator 9 * 10 */ 11 public class Adapter_Person implements Target_Person{ //仅仅实现目标接口 12 private Person person; 13 14 //在构造函数中将Adaptee类Person传递进来 15 public Adapter_Person(Person person){ 16 this.person = person; 17 } 18 19 //实现目标接口中的sayEnglish()--调用Adaptee中的sayEnglish() 20 @Override 21 public void sayEnglish() { 22 this.person.sayEnglish(); 23 } 24 25 //实现接口中的其它方法 26 @Override 27 public void sayFrench() { 28 System.out.println("person can say French!"); 29 } 30 31 @Override 32 public void sayJapanese() { 33 System.out.println("person can say Japanese!"); 34 } 35 }
客户端(Client)
1 package com.bluemsun.objectdapter; 2 3 import com.bluemsun.classadapter.Person; 4 import com.bluemsun.classadapter.Target_Person; 5 6 public class Test { 7 public static void main(String[] args) { 8 Target_Person person = new Adapter_Person(new Person()); 9 10 person.sayEnglish(); 11 person.sayFrench(); 12 person.sayJapanese(); 13 } 14 }
对象适配器可以适配多个带适配的类。只需要你在Adapter的构造方法中传递不同的带适配的类即可。具有灵活性。
类适配器的优点:
1、由于适配器类是适配者类的子类,因此可以再适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
类适配器的缺点:
1、对于Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为接口,不能为类,其使用有一定的局限性,不能将一个适配者类和他的子类同时适配到目标接口。
对象适配器的优点:
1、把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和他的子类都适配到目标接口。
对象适配器的缺点:
1、与类适配器模式相比,要想置换适配者类的方法就不容易。