适配器模式
举个例子,苹果体验店为体验者推出一项免费服务,体验者在店内可以使用提供的充电器进行充电,为此体验店根据人流量,准备了10条苹果充电线,10条安卓充电线,10条微软充电线。
PS:当然了,实际上对霸气的苹果来说,提供的充电器肯定是苹果的啦,这边为了模式就做个假设吧。。。。
各10条就能满足体验者的需求了吗?当然不行,万一有13位体验者的手机是苹果手机,那怎么办,答案就是转接头,店内也需要准备些备用转接头。
上面的例子中有这么几个元素,充电线、转接头、体验者。下面将这些对象对应成代码。
拿安卓手机体验者充电来说
一 充电线,有多种充电线,功能都一样,可以充电,为此需要一个接口以及几个类,代码如下:
1 public interface IphoneCharge { 2 public void phoneCharge(); 3 }
1 public class AppleCharger implements IphoneCharge { 2 public void phoneCharge() { 3 System.out.println("用苹果充电器充电中..."); 4 } 5 }
1 public class MicroCharger implements IphoneCharge { 2 public void phoneCharge() { 3 System.out.println("用微软充电器充电中..."); 4 } 5 }
二 转接头,也有多种,苹果转安卓,微软转安卓等,代码如下
1 public interface Icharge { 2 public void charge(); 3 }
1 public class AppleChargerAdapter extends AppleCharger implements Icharge { 2 @Override 3 public void charge() { 4 super.phoneCharge(); 5 } 6 }
1 public class MicroChargerAdapter extends MicroCharger implements Icharge { 2 @Override 3 public void charge() { 4 super.phoneCharge(); 5 } 6 }
三 安卓体验者,这是客户,他需要的是能实现安卓手机充电的充电线,代码如下:
1 public class MobilephoneHolder { 2 public void charge(Icharge icharge) { 3 icharge.charge(); 4 } 5 }
基本元素都好了之后,客户端调用如下:
1 public static void main(String[] args) { 2 MobilephoneHolder holder=new MobilephoneHolder(); 3 holder.charge(new AppleChargerAdapter()); 4 }
大家可以看到,在第二点中创建的类通过继承于充电线类而调用到充电线类的充电方法,这种方式就叫做类适配器,这是适配器模式的一种形式,另一种形式叫对象适配器,和类适配器基于继承实现不同,对象适配器是基于组合实现的,这种方式相比于类适配器模式更加灵活,解耦性增加了不少。因为充电线有好几种,用类适配器模式的话,转接头类也得随着充电线类,充电线有多少种,转接头也得有几种,万一以后新增不同接口的充电线了,那么转接头也得增加,是不是很麻烦,这个时候我们想着能否有一个通用转接头,来实现所有的转接功能,这个时候就要用到对象适配器。代码如下:
1 public class CommonChargeAdapter implements Icharge{ 2 IphoneCharge iphoneCharge; 3 public CommonChargeAdapter(IphoneCharge i){ 4 this.iphoneCharge=i; 5 } 6 @Override 7 public void charge() { 8 iphoneCharge.phoneCharge(); 9 } 10 }
是不是很方便,当然了,这样做的前提是所有的充电线都实现了充电的接口。
其实对于上面的例子,我们也可以直接修改充电线对应的类,以适应客户端调用的接口需求,这就算是重构了,一般适配器模式的应用是在新系统的某些功能已经在旧系统中有所实现,并且我们并不需要大规模的适配很多遗弃代码,试想一下,如果一个系统中出现了很多适配器,将一个接口封装为另一个接口,这样会让人觉得很不舒服,而且会很疑惑,这种情况下就可以对旧系统直接进行重构。
从上面的代码可以看出,适配器模式的本质是转换匹配,复用功能,从代码的角度上来讲,正是因为由适配器负责处理待转换的被适配者,从而让客户端只需要调用实现特定接口的适配器,这样做也算是隐藏了具体实现,降低了系统的耦合性。
下面是适配器的三个角色:
1 目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
2 需要适配的类(Adaptee):需要适配的类或适配者类。
3 适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。