(九),适配器模式

最后更新于:2022-04-01 09:57:15

记得刚学Java SE的AWT(新版Swing)编程的时候,那个时候自己特别兴奋,因为学了那么久的Java了,没看到一点实在点的东西,觉得很没有成就感。后来学到Swing的时候,用它编写图形化界面,于是写了一个小小的计算器和其他简单的图形化程序。然而,在知道了Java的在图形化界面方面做的不是很好以后,心里有点失望,于是对Swing的热情也慢慢消退了。但是,我并不后悔花了点时间学Swing编程,因为在学习的过程中收获了喜悦,产生了一点小小的成就感,这些就已经够了。呵呵,话又说回来,Java的Swing编程还是值得了解或者学习一下的,因为用它来做一些演示还是挺好的。Java SE的那个Java的Applet(Java应用小程序)就简单了解一下知道Java有这么个小东西就行了,因为现在都基本宣布死亡了。 上面又说了一些废话,不过,学习Swing也是我第一次接触适配器模式,知道有Adapter这个东西。后来,学了用Java作为开发语言的Android开发后,我才更加知道了Java的Swing没有白学,因为不仅可以用Swing编程学一些小的演示程序,而且使得我特别快就上手了Android开发,对Android中的ListView的Adapter模式也特别理解,不仅如此,不知道是不是之前学了Swing还是怎么的,对Android开发非常容易就理解了。到现在,自己可以独立开发Android了。但是,知识学不完,新技术不断,对Android还需要进阶,达到更高的一个层次,让我们一起努力,一起进步。下面,直接进入正题。 定义:把一个类的接口扩展成客户端所期待的另外一个接口,使得原来不能一起使用的两个类(一个接口和一个使用该接口的类)一起工作。 使用场景: 1. 需要一个统一的输入接口,而输入端的类型不可知。这个时候,我们可以暴露一个接口适配器给客户端,让客户端自己定制。如Android的ListView的Adapter; 1. 解决接口不兼容。使得原来的一些接口在新的场景下依旧可以用,而不必写新的接口。 优点: 1. 更好的复用性。系统通过需要使用现有的类,而此类的接口不符合系统的需要,那么通过适配器模式就可以让这些功能得到更好的复用,而避免了写新的接口; 1. 更好的扩展性。通过暴露给客户端一个适配器,让客户端自己定制功能,从而更好地扩展了系统的功能,如Android中既提供了SimpleAdapter,ArrayAdapter还提供了一个抽象适配器BaseAdapter让用户自己定制。 缺点: - 过多使用适配器,让系统杂乱不堪,不易于整体把握。如我们每次都为一个接口写一个是适配器(因为我们不需要实现该接口的所有方法)。 以生活中的裁缝铺为例 代码实现 衣服(接口) ~~~ /** * 衣服(接口) * @author lt * */ public interface Clothes { public int getSize(); } ~~~ 具体的衣服(客户端) ~~~ /** * 具体的衣服(客户端) * @author lt * */ public class Clothes1 implements Clothes{ /** * 假设是180尺码 */ @Override public int getSize() { return 180; } } ~~~ 裁缝铺(适配器) ~~~ /** * 裁缝铺(Adapter) * @author lt * */ public class TailorShop implements Clothes{ private Clothes clothes; public TailorShop(Clothes clothes){ this.clothes = clothes; } /** * 缩短五厘米 */ @Override public int getSize() { return clothes.getSize()-5; } /** * 将衣服拉长5厘米 * @return */ public int largen(){ return clothes.getSize()+5; } } ~~~ 这里的裁缝铺是把衣服缩短5厘米,当然,裁缝铺也可以将衣服变长,也不是固定就是5厘米哦,我们可以用一个参数来让客户端指定修剪长度,如我们将裁缝铺角色改造。 ~~~ /** * 裁缝铺(Adapter) * @author lt * */ public class TailorShop implements Clothes{ private Clothes clothes; /** * 要修剪的长度,正数为拉长,负数缩短 */ private int ds; public TailorShop(Clothes clothes,int ds){ this.clothes = clothes; this.ds = ds; } /** * 缩短五厘米 */ @Override public int getSize() { return clothes.getSize()+ds; } } ~~~ 当然,裁缝铺的功能不仅是改变衣服的尺寸哦,还有缝补衣服。这里就不扩展了,要扩展也就添加方法的事了。 测试(有图有真相): ~~~ public class Test { public static void main(String[] args) { // 小明最近长了5里面,原来180,现在185了,但衣服还是180的 Clothes clothes = new Clothes1(); System.out.println("原来的衣服尺码:"+clothes.getSize()); // 小明说拉长5厘米 TailorShop tailorShop = new TailorShop(clothes,5); System.out.println("经过裁缝捕裁剪后衣服的尺码:"+tailorShop.getSize()); } } ~~~ 结果(Run As): ![这里写图片描述](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-17_56ea5b37a8806.jpg "") 裁缝铺修剪完后,小明顿时非常开心地穿起了原来自己喜欢但穿不了的衣服高兴地… 这个例子向我们演示了两个类(小明和衣服)原本不能一起工作,后来经过适配器(裁缝铺)修剪后又可以一起工作了(小明又穿上那件自己喜欢的衣服了)。其实,这个是对象适配器模式,当然还可以有类适配器模式,这两种模式的区别就是前者为类进行包裹封装,后者直接扩展类(继承)。下面再以一个例子结束本文的内容。 对于下面的这个接口: ~~~ public interface DemoInterface { public void method1(); public void method2(); public void method3(); public void method4(); public void method5(); public void method6(); // ... } ~~~ 我们在使用这个接口的时候,我们每次都要实现6个或者更多的方法,如果我们不需要实现所有的方法,那么我们可以写一个这样的适配器 ~~~ public abstract class DemoAdapter implements DemoInterface{ @Override public abstract void method1(); @Override public void method2() { } @Override public void method3() { } @Override public void method4() { } @Override public void method5() { } @Override public void method6() { } } ~~~ 除了我们必须要实现的method1外,其它不必实现的给个空的实现,不管他。下次,我们使用个适配器代替原来的接口,通常系统也会为我们提供这样的一个适配器,如果没有,我们可以自己写。 总结: 任何的模式都有优缺点,适配器模式也不例外,如上面的抽象适配器就有一个明显的缺点,就是将一个接口替换成了抽象类,优点就是可以不用实现我们不需要实现的方法,而只关心我们必须要实现的那些方法,缺点就是由接口变成了类,使用可能会受限,因为java不支持多重继承,但可以实现多个接口。
';