博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式-适配器模式
阅读量:6361 次
发布时间:2019-06-23

本文共 4341 字,大约阅读时间需要 14 分钟。

hot3.png

一、什么是适配器?

    适配器就是一种适配中间件,将两种不匹配的东西进行适配连接,举一个生活中的例子。小金最近买了最新款的macbook pro,但是发现电脑的数据接口都变成了Type c接口,这导致了之前的所有的 usb设备都不可用。那应该怎么办呢?这个时候就需要淘宝买一个能够将type c 转换成usb的器件,我们称之为适配器。

    那么适配器模式又是什么呢?适配器模式就是从适配器获得的灵感,将两种不太适配的代码进行适配,这种模式就是适配器模式了。

 

二、适配器模式

    适配器模式有类的适配器模式对象的适配器模式两种不同的形式。

 

2.1、类的适配器模式

  • UML关系图

    类的适配器模式将适配者类中的方法继承过来变成目标类的API

    从上图中Target接口可以看出客户端需要 operation1方法和operation2方法,但是Adaptee(适配者类)中只提供了operation1方法,这时通过Adapter(适配器类)继承Adaptee并且补充缺失的operation2方法满足了 客户端的需求。

 

  • 代码演示

//Target.javapublic interface Target {    public void operation1();     public void operation2(); }//Adaptee.javapublic class Adaptee {    public void operation1(){        //do some thing    }}//Adapter.javapublic class Adapter extends Adaptee implements Target {    /**     * 因为Adaptee没有提供operation2方法,     * 所以需要适配器进行补充     */    @Override    public void operation2() {        //do some thing    }}

    上面的代码中我们可以看到适配器类Adapter 继承了适配者Adaptee类,实现了目标接口Target,并且补充了Adaptee中缺少的operation2方法,最终满足了客户端的API需求。

 

2.2、对象适配器模式

  • UML关系图

    与类的适配器模式不同,对象适配器模式不是通过继承连接到Adaptee(适配者),而是通过委派的方式连接Adaptee

    从上图中可以看出客户端需要operation1方法和operation2方法,但是Adaptee类中只提供了operation1方法。为了使客户端能够使用Adaptee,需要一个适配器类,将operation1方法通过 Adaptee实例委派给Adaptee类处理,并且自己实现Adaptee中没有提供的operation2方法。

 

  • 代码演示
//Target.javapublic interface Target {    void operation1();    void operation2();}//Adaptee.javapublic class Adaptee {    public void operation1(){}}//Adapter.javapublic class Adapter implements Target {    public Adaptee adaptee;    public void Adapter(Adaptee adaptee) {        this.adaptee = adaptee;    }    @Override    public void operation1() {        this.adaptee.operation1();    }    @Override    public void operation2() {        //do some thing    }}

从代码中我们看到Adapter适配器类中将operation1方法的实现委派给了Adaptee,并且自己实现了operation2方法,最终满足了客户端的API需求。

 

三、适配器模式在前端中的应用

3.1接口适配

    假设我们引入两种地图组建baiduMap 和 gaodeMap 都提供了相同的 start启动方法

const baiduMap = {  start: function () {    console.log('启动百度地图');  }};const gaodeMap = {  start: function () {    console.log('启动高德地图');  }};const startMap = function (map) {  if (map.show instanceof Function) {    map.start();  }};//我们可以通过startMap方法分别启动两种地图startMap(gaodeMap); // 输出:启动高德地图startMap(baiduMap);  // 输出:启动百度地图

    上面我们可以通过startMap方法分别启动两种地图是因为两种地图的启动方法都是start,但是如果高德地图的启动方法是begin怎么办?这个时候我们就需要用到适配器将启动方法和高德地图进行适配。

const baiduMap = {  start: function () {    console.log('启动百度地图');  }};const gaodeMap = {  begin: function () {    console.log('启动高德地图');  }};const gaodeMapAdapter = {  start : function(){    return gaodeMap.begin();   } }const startMap = function (map) {  if (map.show instanceof Function) {    map.start();  }};//启动高德地图的时候需要将适配器作为参数传入startMap(gaodeMapAdapter); // 输出:启动高德地图startMap(baiduMap);  // 输出:启动百度地图

    上面我们就是通过gaodeMapAdapter将startMap方法 和gaodeMap进行适配,使两者仍人可以正常调用。

 

3.2参数适配

    假如小金的学校为了提高学生们的查询高考成绩效率,自己开发了一套分数查询系统只需要输入证件号码就可以,但是教育部提供的查询api中需要输入省市和学校信息,那这种参数不匹配的情况该怎么办?

var param = {  id : 222404}function queryScore(param) {  var newParam = argAdapter(param);  return EduApi.getScore(newParam);}//教育部提供的接口var EduApi = {  getScore : function(param){     if (!param.province || !param.city || param.school) {       return null;     }     return select(param)  }}//参数适配器function argAdapter(param) {  var newParam = {};  var default = {    province : '江苏',    city : '南京',    school : '南京大学附属中学'  }  newParam.id = param.id;  newParam.province = param.province || default.province;  newParam.city = param.city || default.city;  newParam.school = param.school || default.school;  return newParam}

    上面的代码中 参数适配器argAdapter 将客户端传入的参数 和API中实际需要的参数进行了适配,让代码能够正常地运行。 

 

3.3数据适配

    接触过echarts的人应该知道,要使用echarts展示折线图,需要分别传入x轴和y轴数据,他们的数据格式都是数组格式,但如果后传来的数据是对象数组怎么办,当然是要将对象数组拆分成两组数组。

[{    "x": "huawei",    "y": '9999' }, {    "x": "iphone",    "y": 8888 }, {    "x": "samsung",    "y": 7777}]//x轴适配器function xAxisAdapter(res) {  return res.map(item => item.x);}//获取x轴数据//['huawei', 'iphone', 'samsung']//y轴适配器function yAxisAdapter(res) {  return res.map(item => item.y);}//获取y轴数据//[9999,8888,7777]

 

四、适配者模式优缺点

  • 优点:

    1、将目标类和适配者类解耦

    2、增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性

    3、灵活性和扩展性都非常好,符合开放封闭原则

  • 缺点:

    1、过多的使用适配器,会让系统非常零乱,不易整体进行把握

    2、调用关系太复杂,不利于系统维护

 

五、总结

正如上面文章讲述,适配器模式在我们的前后端代码中都起着重要的作用。但是我们要认识到适配器模式本质上是一个”亡羊补牢”的模式,它解决的是现存的两个接口之间不兼容的问题,你不应该在软件的初期开发阶段就使用该模式。如果我们在设计之初就规划好调用方和被调用方,前端和后端之前统一一下数据格式就没有必要使用适配器模式,如果时间充裕或者没有必要一定是用适配器模式,应该对代码进行重构,使他们之间能够直接匹配。

转载于:https://my.oschina.net/kimyeongnam/blog/3026273

你可能感兴趣的文章
递归算法学习系列之三(快速排序)
查看>>
从TdataSet生成OleVariant
查看>>
预告和目录: Wayne Game Solution 0.1 网络游戏大厅 从最基础开始
查看>>
xBIM WeXplorer xViewer的导航,相机、剖切、隐藏 等操作
查看>>
(转)预编译头文件
查看>>
艾伟_转载:浅析IHttpModule和IHttpHandler
查看>>
百万级访问量网站的技术准备工作
查看>>
Gnome Tweak Tool 3.0.5发布
查看>>
杭州鼎家被曝破产:长租公寓过度金融化酿恶果
查看>>
刘慈欣点赞科幻电影《流浪地球》:震撼心灵
查看>>
香港将发展中央儿童数据资料库 研究整合各部门数据
查看>>
安徽凤阳警方打掉一假证团伙 成员多为校长和老师
查看>>
2018年末个人住房贷款余额25.75万亿元 同比增17.8%
查看>>
“中国女梅西”王霜的24岁:不负过去,不惧未来
查看>>
云南会泽举办高山滑雪公开赛
查看>>
美国东部遭冬季风暴侵袭 全美近2000航班取消
查看>>
香港西九新地标戏曲中心开幕 特首冀向世界展现中国戏曲精髓
查看>>
Android密钥库的发展历史和使用指南
查看>>
iOS推送SDK集成对比
查看>>
解析JavaScript异步加载
查看>>