您的位置:首页 > 职场人生

设计模式(四)适配器模式

2018-03-17 18:05 399 查看
版权声明:转载必须注明本文转自晓_晨的博客:http://blog.csdn.net/niunai112

相关系列文章

设计模式之六大设计原则

设计模式(一)单例模式

设计模式(二)工厂模式

设计模式(三)策略模式

本篇导航

类适配器模式

对象适配器迷失

接口适配器模式(缺省适配器模式)

前言

这篇让我们学习一下适配器模式,适配器模式是作为两个不兼容的接口之间的桥梁。

让我们设想一下,当一个已经实现好的方法需要A类型的参数,但是我们只有一个可以返回B类型的方法的时候,这个时候该怎么办呢?1.修改前面那个的方法,让他能接受参数A。2.修改后面那个方法,使得他能返回参数A。3.创建一个方法,使得参数B能转换成A。但基于开闭原则,我们倾向于第三个解决方案,第一种和第二种都需要修改代码,而且有可能已经有其他的对象已经使用了他们,所以不好在动,但是实际的情况得按具体来分析。这是一个抽象理解。

LZ来举一个栗子!

当LZ新买了一台电脑的时候,发现核显(穷的买不起独显)的接口是VGA的接口,但是LZ买到的显示器却没有VGA的接口,有HDMI的接口,这个时候,LZ就只能把VGA转成HDMI,让显示器正常工作。用代码来展示就如下面所示:

类适配器模式

/***
*
*@Author ChenjunWang
*@Description:VGA接口
*@Date: Created in 16:02 2018/3/17
*@Modified By:
*
*/
public interface VGAInterface {
public void outputVGASignal();
}

/***
*
*@Author ChenjunWang
*@Description:HDMI接口
*@Date: Created in 16:03 2018/3/17
*@Modified By:
*
*/
public interface HDMIInterface {
public void outputHDMISignal();

}

/**
*
*@Author ChenjunWang
*@Description:VGA信号输出类
*@Date: Created in 15:57 2018/3/17
*@Modified By:
*
*/
public class VGA implements VGAInterface{

public void outputVGASignal(){

System.out.println("这里输出的是VGA的信号");
}
}
/***
*
*@Author ChenjunWang
*@Description:VGA转成HDMI的类(适配器类)
*@Date: Created in 16:03 2018/3/17
*@Modified By:
*
*/
public class VGA2HDMI extends VGA implements HDMIInterface {
@Override
public void outputHDMISignal() {
outputVGASignal();
System.out.println("转换过程…………");
System.out.println("输出HDMI信号");
}
}

/***
*
*@Author ChenjunWang
*@Description:电脑测试类
*@Date: Created in 16:03 2018/3/17
*@Modified By:
*
*/
public class Computer {
public static void main(String[] args) {
VGA2HDMI vga2HDMI = new VGA2HDMI();
vga2HDMI.outputHDMISignal();
}
}

输出结果
--------------------------
这里输出的是VGA的信号
转换过程…………
输出HDMI信号


UML图



上面的就是类适配器模式了,要继承输入的类,自己实现输出接口。按上面来写会有一个问题,那就是VGA2HDMI类可以使用VGA的方法,也就是说他能直接输出VGA信号,但对于程序猿来说,应该把错误防范于未然,那就是让外面看不到里面有这个方法。

对象适配器模式

在这里LZ只修改了VGA2HDMI类,他不在需要继承VGA了,内部有个VGA的私有变量,这样以来,按正常流程来走(不包括反射),外界就看不到里面有VGA这个字段,而且也调用不到方法了,当初始化的时候,外部传入VGA的类,里面就能直接得到里面的东西了,在这里是VGA的信号,然后实现outputHDMISignal方法将信号转为HDMI。

第二个修改的类是Computer,在实例化适配器VGA2HDMI的时候,需要传入VGA的实例,否则无法转换,因为都没信号输入了,没有办法转换啊。

import adapter.HDMIInterface;

public class VGA2HDMI  implements HDMIInterface {
private VGA vga;
VGA2HDMI(VGA vga){
this.vga = vga;
}
@Override
public void outputHDMISignal() {
vga.outputVGASignal();
System.out.println("转换过程…………");
System.out.println("输出HDMI信号");
}
}

public class Computer {
public static void main(String[] args) {
VGA2HDMI vga2HDMI = new VGA2HDMI(new VGA());
vga2HDMI.outputHDMISignal();
}
}
运行结果
------------------------------------------------
这里输出的是VGA的信号
转换过程…………
输出HDMI信号


UML图



接口适配器模式(缺省适配器模式)

当一个接口的方法声明太多的时候,有点子类不需要实现这么多方法。比如一个屏幕的接口,他抽象出了能得到VGA,HDMI,DVI,DP信号的方法。但是,实际上,到手的显示器都没有这么多的接口可以用,有其中的2-3个接口。

比如一块X牌子的显示器,只能接收VGA和HDMI信号,那么他的另外2个方法就得为空了,因为他没办法处理。

/***
*
*@Author ChenjunWang
*@Description:屏幕接口
*@Date: Created in 16:58 2018/3/17
*@Modified By:
*
*/
public interface Screen {
public void getVGASignal();
public void getHDMISignal();
public void getDVISignal();
public void getDPSignal();
}

/***
*
*@Author ChenjunWang
*@Description:
*@Date: Created in 17:01 2018/3/17
*@Modified By:
*
*/
public class XSrceen implements Screen {
@Override
public void getVGASignal() {
System.out.println("显示器显示!");
}

@Override
public void getHDMISignal() {
System.out.println("显示器显示!");
}

@Override
public void getDVISignal() {

}

@Override
public void getDPSignal() {

}
}


这个时候,就可以创建一个类默认实现了里面所有的方法,其实是不做任何处理,这个时候一个Y牌的显示器继承默认的显示器,只需要重写自己想要的方法就行了。

/***
*
*@Author ChenjunWang
*@Description:
*@Date: Created in 17:03 2018/3/17
*@Modified By:
*
*/
public class DefaultScreen implements Screen{
@Override
public void getVGASignal() {

}

@Override
public void getHDMISignal() {

}

@Override
public void getDVISignal() {

}

@Override
public void getDPSignal() {

}
}

/***
*
*@Author ChenjunWang
*@Description:
*@Date: Created in 17:04 2018/3/17
*@Modified By:
*
*/
public class YScreen extends DefaultScreen {
@Override
public void getHDMISignal() {

System.out.println("显示器显示!");
}

@Override
public void getDVISignal() {

System.out.println("显示器显示!");
}
}


uml图



因为接口设计的最小化只是理想状态,难免会有一些实现类,对其中某些方法不感兴趣,这时候,如果方法过多,子类也很多,并且子类的大部分方法都是空着的,那么就可以采取这种方式了。可以减少类里面的代码量。

当然,这样做违背了里氏替换原则,但是上面的做法原本就违背了接口的最小化原则,所以我们在真正使用时要权衡二者的利弊,到底我们需要的是什么。所以从此也可以看出来,原则只是指导,并不一定也不可能全部满足,所以我们一定要学会取舍。

各种规则毕竟都只是理想化的东西,在实际项目中应该根据实际情况进行合理的变通。假如你是超级无敌大牛,那可以无视LZ说的话~~~~

回到最上方

有什么不懂或者不对的地方,欢迎留言。

喜欢LZ文章的小伙伴们,可以关注一波,也可以留言,LZ会回你们的。

觉得写得不错的小伙伴,欢迎转载,但请附上原文地址,谢谢^_^!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息