适配器模式
适配器模式
设计模式--->简单来说,就是将简单问题复杂化,这样就提高了可扩展性,灵活性,可维护性,可复用性。
引言:
说起适配器,真是太熟悉了,生活中适配器无处不在,蓝牙适配器,电源适配器,网卡适配器等等,为什么适配器有这么多的市场呢,还不是因为我们要用的东西与我们已经在使用的东西接口不匹配造成的,设想一下,全世界由一家厂商生产一切,这个问题是否可以解决呢,答案是否定的,这样反而阻碍了科技的进步,效率的低下,有竞争才有活力,那么正常的情况是,有很多的厂家,现在的厂家也越来越专业,只专注生产自己的产品,这些厂家协商好统一的接口,以便用户能很好的组装在一起使用,然后凡事不是完美的,我们没有必要也不能为了一味的追求统一的接口,而将不同的领域的产品去强迫统一,这样反而照成了反作用了,比如说我们不能因为现在的计算机的需要供给的电源电压不高,而将所有的发电电压都弄得很低,这样显然是不行的,这种问题解决起来也很好办,用一个适配器就可以解决了...
编程世界:
回到软件设计中,适配器凸显在一个个的对象中,在代码的字里行间彰显着它的魅力,当我们提供给客户一个他们觉得很好使用且很习惯的接口时,而且他们也正乐此不疲的疯狂享受着,这时,客户的需求增加了,而我们不会去更改原来已经成熟的应用程序的接口,我们就需要创建新的类和功能,然而能和以前的接口一致是最好的,因为这样客户就不需要改变他们的使用方式,因为他们也不愿意改变,如果接口不一致呢,我们就需要适配器了,所以说适配器不是首选的,而是在必要时才用到的,当然有人会说,把整个系统换了,换成行的接口,这样也可以解决问题,但花的代价有点大了,特别是一个系统的使用不久时,所以适配器无疑使不二的选择,它能将一个类的接口转化成用户希望的另一个接口,使得原本由于接口不兼容而不能在一起工作的那些个类可以一起工作了。
故事背景:
小时候,家里有一台黑白的电视机,那时村里有电视机是很不得了的事情,但我没觉得多优越,黑白倆色,感觉回到了解放前了。那时候,有线电视不发达,在我们那没有,数字电视就不用说了,那时候是靠电视机的两根天线,像小时候看的动画片的机器人的两耳朵一样,夸张的是,还要用一根长长的竹竿搭载着天线在上面接受信号,由于种种限制,收到的电视台少之又少,但能听听外边的新闻,也足以让很多邻里街坊的是不是凑上来听听,所以那时候家里比较热闹。时代进步了,过了几年,村里拉进来有线电视,那时候的有线电视比起天线的可相当于高科技了,但不巧的是,我家那黑白电视机不能正常播放这种电视信号,怎么办呢?换电视机,不划算,不经济,家里又不是钱很多,况且,这黑白电视机没用多久,于是老爸就弄了个适配器,经过中转后能播放了,可高兴了,因为可以看体育世界了,这就影响了我以后对体育的热爱...
菜鸟面向对象分析与设计:
将上面的无线到有线的转换,而且不用换电视机的场景,映射到程序世界中,因为只要是对象,就可以用面向对象的思想去分析和实现,这个理解起来很容易。
对象的提取和职能和交互:
无线电视:WirelessTV(interface) --> public void wirelessTVShow();
有线电视:WiredTV(interface) --> public void wiredTVShow();
适配器:(TVAdapter) --> public void wirelessTVShow(); //适配器与无线电视信号有相同的接口,在这个方法中调用的是有线电视信号的方法
电视机(TVClient)--> public void play(WirelessTV wirelessTV) //黑白电视机只能正常播放无线电视信号
UML类图:
菜鸟写代码:
无线电视信号:
WirelessTV(interface):
public interface WirelessTV { /** * 无线电视台展示节目 */ public void wirelessTVShow(); }
WirelessCCTV_1:
public class WirelessCCTV_1 implements WirelessTV { @Override public void wirelessTVShow() { //这里可以使处理业务的一些代码,简化问题,打印来模拟了 System.out.println("Hello everyone,this is wirelessCCTV_1,welcome to back..."); System.out.println("新闻联播马上开始..."); } }WirelessCCTV_6:
public class WirelessCCTV_6 implements WirelessTV { @Override public void wirelessTVShow() { //这里可以使处理业务的一些代码,简化问题,打印来模拟了 System.out.println("Hello everyone,this is wirelessCCTV_6,welcome to back..."); System.out.println("又到了囧季,人在囧途之泰囧即将上映..."); } }
WirelessCCTV_8:
public class WirelessCCTV_8 implements WirelessTV { @Override public void wirelessTVShow() { //这里可以使处理业务的一些代码,简化问题,打印来模拟了 System.out.println("Hello everyone,this is wirelessCCTV_8,welcome to back..."); System.out.println("人文历史,经典故事,尽在央视8套..."); } }
WiredTV(interface):
public interface WiredTV { /** * 有线电视台展示节目 * 电视信号升级了,此时的接口方法名称不一致 */ public void wiredTVShow(); }
WiredCCTV_5:
public class WiredCCTV_5 implements WiredTV { @Override public void wiredTVShow() { // 这里可以使处理业务的一些代码,简化问题,打印来模拟了 System.out .println("Hello everyone,this is wirelessCCTV_5,welcome to back..."); System.out.println("NBA 全明星赛进行中..."); } }
好了,要看电视啦:
import com.ysjian.adapter.adapter.TVAdapter; import com.ysjian.adapter.wiredtv.WiredCCTV_5; import com.ysjian.adapter.wiredtv.WiredTV; import com.ysjian.adapter.wirelesstv.WirelessCCTV_1; import com.ysjian.adapter.wirelesstv.WirelessCCTV_6; import com.ysjian.adapter.wirelesstv.WirelessCCTV_8; import com.ysjian.adapter.wirelesstv.WirelessTV; public class TVClient { public static void main(String[] args) { // 黑白电视机,能播放无线电视 TVClient tv = new TVClient(); // 无线电视 WirelessTV t1 = new WirelessCCTV_1(); WirelessTV t6 = new WirelessCCTV_6(); WirelessTV t8 = new WirelessCCTV_8(); // 电视机正常播放无线电视信号 tv.play(t1); tv.play(t6); tv.play(t8); // 这个是有线电视信号,怎么办呢? WiredTV t5 = new WiredCCTV_5(); // tv.play(t5);//这里不能将有线的电视信号给黑白电视机播放 // 用适配器进行适配 TVAdapter tvAdapter = new TVAdapter(t5); // 将适配后的电视信号传给电视机 tv.play(tvAdapter); } /** * 电视机播放功能,只能接受无线的电视信号,这个特定的电视机不能改变 * * @param wirelessTV */ public void play(WirelessTV wirelessTV) { wirelessTV.wirelessTVShow(); } }
上面播放无线电视信号时很正常的播放了,但来了一个有线电视信号怎么办呢,这就用到了适配器了,核心适配器登场了
适配器(TVAdapter):
import com.ysjian.adapter.wiredtv.WiredTV; import com.ysjian.adapter.wirelesstv.WirelessTV; public class TVAdapter implements WirelessTV { private WiredTV wiredTV;// 要被适配的接口 public TVAdapter(WiredTV wiredTV) { this.wiredTV = wiredTV; } /** * 进过适配以后,可以通过原来的接口同一调用了,客户端电视机就能播放有线电视了 */ @Override public void wirelessTVShow() { wiredTV.wiredTVShow(); } }
适配器很简单了,其实就是一个宗旨:适配器要要与用户已经成熟使用接口一致,在适配器去进行对新增功能的接口的调用,这样用户就仍然按照原来的方式调用这个新增的功能了。
简单总结一下:菜鸟往往会认为,有了适配器模式,什么都可以不怕了,碰到接口不一致时就用它,这样就可以肆无忌惮的设计了,这是一个严重的错误,如果在设计初期有预见性的接口的不一致,要尽量避免这个问题,是接口设计一致,降低系统的复杂性,为后期的维护减低难度和降低成本。在后期维护时,碰到了双方都难以修改时可以考虑用适配器。另外当开发一个用程序中,一开始要用到第三方组件,往往第三方组件的接口与我们自己设计的接口不同的,当然如果完全迎合它的接口是可以的,但这不推荐,没有这个必要,此时适配器用在了开发的设计阶段的。
黑白电视机最终还是被历史淘汰,后来家里买了台彩电,从此,这个电视信号适配器就下岗了...
结语:凡事无绝对,雪中送炭总比锦上添花来的更让人感人,让自己成为一个他人需要的人是要付出真心的,做好自己...