基础编程学习快乐每一天
首页
留言
Siddim.com
当前位置:
首页
>
编程知识库
>
后端开发知识
>
设计模式是什么鬼(适配器)
设计模式是什么鬼(适配器)
阅读
1
2018-07-25
作者:凸凹里歐
来源:轻文社 微信号:
Todd
-
Leo
知音专栏
程序员的出路
写程序时该追求什么,什么是次要的?
如何准备
Java
初级和高级的技术面试
设计模式系列文章点击阅读原文直达,欢迎交流讨论
我们这个世界,充满着千奇百怪的对象,更有趣的是对象与对象间是存在着互动,沟通,这样世界才变得美妙。那到底是怎样互动呢?靠什么才能互动呢?是的,接口。比如你和朋友一起喝茶聊天,我们暂且不管声带,耳膜这些功能性对象, 那你们之间聊天的接口就是嘴巴耳朵了,嘴巴发送声波,耳朵接收声波,接口,一定是输入或输出的终端。
好了,这是语言沟通,那如果是行为沟通呢,比如在一个夜黑风高的晚上,你跟你的另一半偷偷钻进了高粱地里并做了一些丧尽天良的事情,到底是通过什么接口互动呢?好吧,这个难题留个你了,好好研究一下留言给我。
好了我们言归正传,如果说你跟毛里求斯人交流,你们之间的接口对接失效了,说什么完全根本听不懂!怎样跨越语言的鸿沟?找个翻译吧,那我们说这个翻译就扮演了一个适配器(
Adapter
)的角色,其实翻译官们为中日友好做出了巨大贡献,别说是吃你几个烂西瓜。
顾名思义,适配器,得适应当前的不同配置,解决兼容性问题。我们生活中充满了各种各样的适配器,上网用的调制解调器(
modem
)就是一种数模转换的适配器,俗称“猫”,不过现在都是光猫了,也就是光信号和电信号的互相转化,其实道理是一样的,还有各种变压器也属于电压转换的适配器。
如果觉得还不够形象可以看一下家里的电器,比如你的电视是两项插头,墙上的插孔是三项插孔怎么办?哦,有人说把插头掰弯强行插入!那如果是三项插头接两项插孔呢?把零线插针拔了!呃,我只能说这是暴力破解!违反设计模式原则。言归正传,我们还是不要随便破坏现有的类,那我们需要的是一个转换器,用优雅微妙的方式化解这种不兼容情况。
举个例子,我们开始代码部分,先写墙上的三项插孔接口,命名
TriplePin
:
public
%
20interface
%
20TriplePin
%
20
%
7B
%
0A
%
20
%
20
%
20
%
20
//%
E5
%
8F
%
82
%
E6
%
95
%
B0
%
E5
%
88
%
86
%
E5
%
88
%
AB
%
E4
%
B8
%
BA
%
E7
%
81
%
AB
%
E7
%
BA
%
BFlive
%
EF
%
BC
%
8C
%
E9
%
9B
%
B6
%
E7
%
BA
%
BFnull
%
EF
%
BC
%
8C
%
E5
%
9C
%
B0
%
E7
%
BA
%
BFearth
%
0A
%
20
%
20
%
20
%
20public
%
20void
%
20electrify
(
int
%
20l
,%
20int
%
20n
,%
20int
%
20e
);%
0A
%
7D
%
0A
我们只定义三插孔标准
electrify
(通电)方法,三个参数分别是火线、零线、地线,很简单吧,同样地接下来是两项插孔接口,只是少了地线,命名
DualPin
:
public
%
20interface
%
20DualPin
%
20
%
7B
%
0A
%
20
%
20
%
20
%
20public
%
20void
%
20electrify
(
int
%
20l
,%
20int
%
20n
);//%
E8
%
BF
%
99
%
E9
%
87
%
8C
%
E6
%
B2
%
A1
%
E6
%
9C
%
89
%
E5
%
9C
%
B0
%
E7
%
BA
%
BF
%
0A
%
7D
%
0A
请注意,这个并不是我们的墙上的目标接口,而是电视机的两插标准。好了继续,我们的
TV
登场了,用的是两项插头,当然它实现的是
DualPin
的标准,
Let
'
s
keep
it
simple
,命名
TV
:
public
%
20class
%
20TV
%
20implements
%
20DualPin
%
20
%
7B
%
0A
%
0A
%
20
%
20
%
20
%
20
@
Override
//%
E6
%
97
%
A2
%
E7
%
84
%
B6
%
E6
%
98
%
AF
%
E4
%
B8
%
A4
%
E9
%
A1
%
B9
%
E6
%
8F
%
92
%
E5
%
A4
%
B4
%
EF
%
BC
%
8C
%
E5
%
BD
%
93
%
E7
%
84
%
B6
%
E5
%
AE
%
9E
%
E7
%
8E
%
B0
%
E4
%
B8
%
A4
%
E9
%
A1
%
B9
%
E6
%
8F
%
92
%
E6
%
A0
%
87
%
E5
%
87
%
86
%
0A
%
20
%
20
%
20
%
20public
%
20void
%
20electrify
(
int
%
20l
,%
20int
%
20n
)%
20
%
7B
%
0A
%
20
%
20
%
20
%
20
%
20
%
20
%
20
%
20System
.
out
.
println
(%
22
%
E7
%
81
%
AB
%
E7
%
BA
%
BF
%
E9
%
80
%
9A
%
E7
%
94
%
B5
%
EF
%
BC
%
9A
%
22
%
20
%
20l
);%
0A
%
20
%
20
%
20
%
20
%
20
%
20
%
20
%
20System
.
out
.
println
(%
22
%
E9
%
9B
%
B6
%
E7
%
BA
%
BF
%
E9
%
80
%
9A
%
E7
%
94
%
B5
%
EF
%
BC
%
9A
%
22
%
20
%
20n
);%
0A
%
20
%
20
%
20
%
20
%
7D
%
0A
%
0A
%
7D
%
0A
那么问题来了,墙上的接口是三插标准,电视实现的是两插标准,无法通电。怎么办?把电视拆了重新修改实现三插标准么?暴力份子你又来?答案显然是否定的,既然是设计模式,果断转换插头啊!好,写个
Adapter
解决他们之间不可调和的矛盾。
%
201public
%
20class
%
20Adapter
%
20implements
%
20TriplePin
%
20
%
7B
%
0A
%
202
%
0A
%
203
%
20
%
20
%
20
%
20private
%
20DualPin
%
20dualPinDevice
;%
20
%
0A
%
204
%
0A
%
205
%
20
%
20
%
20
%
20
//%
E5
%
88
%
9B
%
E5
%
BB
%
BA
%
E9
%
80
%
82
%
E9
%
85
%
8D
%
E5
%
99
%
A8
%
E5
%
9C
%
B0
%
E6
%
97
%
B6
%
E5
%
80
%
99
%
EF
%
BC
%
8C
%
E9
%
9C
%
80
%
E8
%
A6
%
81
%
E6
%
8A
%
8A
%
E5
%
8F
%
8C
%
E6
%
8F
%
92
%
E8
%
AE
%
BE
%
E5
%
A4
%
87
%
E6
%
8E
%
A5
%
E5
%
85
%
A5
%
E8
%
BF
%
9B
%
E6
%
9D
%
A5
%
0A
%
206
%
20
%
20
%
20
%
20public
%
20Adapter
(
DualPin
%
20dualPinDevice
)%
20
%
7B
%
0A
%
207
%
20
%
20
%
20
%
20
%
20
%
20
%
20
%
20this
.
dualPinDevice
%
20
=%
20dualPinDevice
;%
0A
%
208
%
20
%
20
%
20
%
20
%
7D
%
0A
%
209
%
0A10
%
20
%
20
%
20
%
20
//%
E9
%
80
%
82
%
E9
%
85
%
8D
%
E5
%
99
%
A8
%
E5
%
AE
%
9E
%
E7
%
8E
%
B0
%
E7
%
9A
%
84
%
E6
%
98
%
AF
%
E7
%
9B
%
AE
%
E6
%
A0
%
87
%
E6
%
8E
%
A5
%
E5
%
8F
%
A3
%
0A11
%
20
%
20
%
20
%
20
@
Override
%
0A12
%
20
%
20
%
20
%
20public
%
20void
%
20electrify
(
int
%
20l
,%
20int
%
20n
,%
20int
%
20e
)%
20
%
7B
%
0A13
%
20
%
20
%
20
%
20
%
20
%
20
%
20
%
20
//%
E5
%
AE
%
9E
%
E9
%
99
%
85
%
E4
%
B8
%
8A
%
E8
%
B0
%
83
%
E7
%
94
%
A8
%
E4
%
BA
%
86
%
E8
%
A2
%
AB
%
E9
%
80
%
82
%
E9
%
85
%
8D
%
E8
%
AE
%
BE
%
E5
%
A4
%
87
%
E7
%
9A
%
84
%
E5
%
8F
%
8C
%
E6
%
8F
%
92
%
E9
%
80
%
9A
%
E7
%
94
%
B5
%
EF
%
BC
%
8C
%
E5
%
9C
%
B0
%
E7
%
BA
%
BFe
%
E8
%
A2
%
AB
%
E4
%
B8
%
A2
%
E5
%
BC
%
83
%
E4
%
BA
%
86
%
E3
%
80
%
82
%
0A14
%
20
%
20
%
20
%
20
%
20
%
20
%
20
%
20dualPinDevice
.
electrify
(
l
,%
20n
);%
0A15
%
20
%
20
%
20
%
20
%
7D
%
0A16
%
0A17
%
7D
%
0A
注意了最关键最精华的部分来了,第
3
行代码意味着这个适配器内部是有一个双插接口的,对于任何双插标准的设备都是可以兼容的
OK
吗?不明白赶紧看看你家里的适配器。第
6
行的代码完成的过程实际就是你把电视插头接入
Adapter
了,其实适配器并不在意是什么设备,洗衣机冰箱都可以的,只要是双插标准就可以接入(第一节讲过的多态概念)。第
12
行通电方法实现的是三插标准,但方法体内部第
14
行实际上是在给“某个设备”(是什么设备就看你接什么了)的双插供电,地线
e
那个参数是用不上的,所以就没有接通,很清晰透彻吧?
当然,除了以上的注入插头的方式(对象适配),还有另一种更简单的方式叫做“类适配器”我们来看下:
1public
%
20class
%
20ClassAdapter
%
20extends
%
20TV
%
20implements
%
20TriplePin
%
7B
%
0A2
%
0A3
%
20
%
20
%
20
%
20
@
Override
%
0A4
%
20
%
20
%
20
%
20public
%
20void
%
20electrify
(
int
%
20l
,%
20int
%
20n
,%
20int
%
20e
)%
20
%
7B
%
0A5
%
20
%
20
%
20
%
20
%
20
%
20
%
20
%
20super
.
electrify
(
l
,%
20n
);%
0A6
%
20
%
20
%
20
%
20
%
7D
%
0A7
%
0A8
%
7D
%
0A
看出来区别没有?这里并没有注入插头(对象组合),而是把电视机给继承了,这样就可以直接调用父类(
TV
)的双插通电而不是注入进来去调用,缺点大家也看到了,这适配器继承为
TV
儿子专用了,洗衣机是用不了啦,作死?其实也不是完全不好,要看具体应用场景哈。
至此,我们的
Adapter
就差不多完成了,以后再也不用破坏插头了,因为这样重写接口或者修改类的代价太大,如果其他类还有依赖的话,那统统要修改,引入了没有必要的重构,总之暴力修改是违反设计模式的基本原则的,开闭原则,指的就是对扩展开放,而对修改关闭,也就是说不要去改动原始类,而是扩展现有功能,提供另一种机制让整个系统实现想要的功能。
最后说下那些概念,归类,名字,什么“类适配器”,“对象适配器”啊,其实,理解不了就算了无所谓,真正的意义在于怎么样在实际工作中灵活运用,实现方式是无穷无尽的,道不清说不尽的,没必要太纠结它到底叫什么,归于哪一类,掌控其背后的道才是最根本的,正如李耳君所言:“道可道,非常道。名可名,非常名。”
推荐大而全的【后端技术精选】
以上数据来源于网络,如有侵权,请联系删除。
上一篇:
设计模式是什么鬼(原型)
下一篇:
面试官:谈谈MySQL是如何解决幻读问题的?
评论
(0)
提交
类别
基础编程学习
HTML
PHP
Python
编程知识库
后端开发知识
热门文章
Java并发中的同步容器与并发容器,你了解多少?
Innodb中的事务隔离级别和锁的关系,难倒一半面试者!
SpringBoot + minio实现分片上传、秒传、续传
面试官:你知道消息队列如何保证数据不丢失吗?
JAVA知识 Java8新特性
面试官:谈谈为什么要限流,有哪些限流方案?
说说动态代理与静态代理区别
面试官:思考Tomcat 类加载器为什么要违背双亲委派模型?
boot-admin 基于SpringBoot的后台权限管理系统,可作为脚手架,用于快速搭建项目
SpringBoot+Vue+App+硬件实现智能家居系统项目