结构模式--之--适配器模式
结构模式:描述如何将类或者对象结合在一起形成更强大的结构。结构模式描述两种不同的东西:类与类的实例。根据这一不同,结构模式可以分为类的结构模式和对象的结构模式
1.类的结构模式:类的结构模式使用继承来把来,接口等组合在一起,以形成更强大的结构。当一个类从父类继承并实现某接口时,这个新的类就把父类的结构和接口的结构结合起来,类的结构模式是静态的。一个类的结构模式的典型例子,就是类形式的适配器模式。
2.对象的结构模式:对象的结构模式描述怎样把各种不同类型的对象组合在一起,以实现新的功能的方法。对象的结构模式是动态的。一个典型的对象的结构模式就是代理人模式,其他的例子包括合成模式,享元模式,装饰模式以及对象形式的适配器模式等。
有一些模式会有类形式和对象形式两种,适配器模式就是这样,它有类形式和对象形式两种。
-----------------------------------------------------------------------------------------------------------------------------
适配器模式 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
适配器有两种:
(一).类的适配器模式:把被适配的类的API转换成目标类的API
1.目标(Target)角色:就是所期待的接口,注意,这里讨论的是类适配器模式,因此目标不可以是类
2.源(Adaptee)角色:现在需要适配的接口
3.适配器(Adapter)角色:适配器为是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色可以是接口,而必须是具体类。
假设我想要一只会飞的狗,只有鸟才会飞,那么就让这个superDog去适配鸟,以下为样例代码
1 public class ClassAdapterTest { 2 3 public static void main(String[] args) { 4 Target dog = new superDog(); 5 dog.run(); 6 dog.fly(); 7 } 8 9 } 10 //目标角色,也就是与客户打交道的接口 11 interface Target{ 12 public void run(); 13 public void fly(); 14 } 15 //源角色,它是需要适配接口或类 16 class bird{ 17 public void fly(){ 18 System.out.println("I can fly"); 19 } 20 } 21 //适配角色,它所源接口转换成目标接口 22 class superDog extends bird implements Target{ 23 //因为在源角色中没有此方法,所以在此要实现 24 @Override 25 public void run() { 26 System.out.println("I can run"); 27 } 28 29 }
(二).对象的适配器模式:
它把被适配的类的API转换成目标类的API,与类的适配器模式不同的是,对象的适配器模式不是使用类继承关系连接到Adaptee类,而是使用委派关系连接到Adapter类。(把Adaptee类作为Adapter类的一个属性引用)
1.目标(Target)角色:这是所期待的接口,目标可以是具体的或抽象的类
2.源(Adaptee)角色:现在需要适配的接口
3.适配器(Adapter)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口,显然,这一角色必须是具体类。
同样以上面的superDog为例,如果使用对象的适配器模式,示例代码如下:
1 public class ObjectAdapter { 2 3 public static void main(String[] args) { 4 //可以看到此处是适配的new Bird()对象 5 Target superDog = new SuperDog(new Bird()); 6 superDog.run(); 7 superDog.fly(); 8 } 9 10 } 11 12 //目标角色,也就是与客户打交道的接口 13 interface Target{ 14 public void run(); 15 public void fly(); 16 } 17 //源角色,它是需要适配接口或类 18 class Bird{ 19 public void fly(){ 20 System.out.println("I can fly"); 21 } 22 } 23 //适配角色,它所源接口转换成目标接口,此处并没有类继承源角色而只是引用 24 class SuperDog implements Target{ 25 private Bird bird; 26 27 public SuperDog(Bird bird){ 28 this.bird = bird; 29 } 30 //因为在源角色中没有此方法,所以在此要实现 31 @Override 32 public void run() { 33 System.out.println("I can run"); 34 } 35 //调用源角色的方法实现接口方法 36 @Override 37 public void fly() { 38 bird.fly(); 39 } 40 }
在什么情况下使用适配器模式?
1.系统需要使用现有的类,而此类的接口不符合系统的需要
2.想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。这些源类不一定有很复杂的接口。
3.(对对象的适配器模式而言)在设计里,需要改变多个已有的子类的接口,如果使用类的适配器模式,就要针对每一个子类做一个适配器类,而这不太实际。
缺省适配器模式为一个接口提供缺省实现,这样子类型可以从这个缺省实现进行扩展,而不必从原有接口进行扩展。作为适配器模式的一个特例,缺省适配器模式在Java语言中有着特殊的应用。