设计模式(一)适配器模式与外观模式
这两天刚把适配器模式与外观模式学习了一遍,记录一下自己在学习中的思考。
适配器设计模式与外观设计模式所涉及到的一个设计原则:
最少知识原则:不要让太多的类耦合在一起,以免当修改了某一部分后,会影响到其他部分。
对于任何对象而言,在该对象的方法内,其中最少所指的范围:
1. 该对象本身;
2.被当作方法的参数传递进来的对象
------------------------------------(以上两点比较好理解,完全字面意思)
3. 此方法所创建或实例化的任何对象
即在方法中,通过构造器生成的一个其他类的对象,在方法中使用这个对象是满足最小知识的原则的;
但是,假如在方法中,通过其他类的非构造器方法返回的类对象,根据该原则是不建议去调用此对象的相关方法的。
4. 对象的任何组件
包括对象所处的类的其他方法,属性
一. 适配器模式
在接触java这门编程语言的时候,看着视频教程,学到过有关适配器模式的相关内容,可是当时自己完全弄不明白(即使到现在,自己依旧有许多不明白的地方),也许是刚接触的原因,经验不足,缺乏实践的学习使得自己在学的时候,总会把许多理念搞混。
说到适配器设计模式,其实分为两类,一种是对象适配器,另一种是类适配器(但java中这种方式是无法实现的)。搞清楚适配器模式,我个人认为最重要的就是分清楚适配对象是谁,被适配对象是谁。简单的说:适配对象就是我想要访问与使用的类,被适配对象则是实际提供功能的类。拿快被用烂的插座的例子来说:
首先是被适配对象--三孔插座:
假设,我想要连上电源的是一个两孔的(嗯。。。比如两孔的落地式电风扇)
即目标对象(适配对象)--两孔插头:
所以需要适配器,让两孔的插头插在适配器上,然后,再将适配器插在三孔的插座上。那么,也就是说适配器会具有两孔的孔洞以及三角的插头,适配器与被适配对象以及目标对象都有联系。
接着回到程序:
适配器与两者都具有关系,但是使用者用的是两孔的插头(即目标对象),那么,从联系上说,目标对象与适配器其实是属于一类的,考虑到目标对象可以不止一类,那就可以考虑将目标对象抽象为一个接口(一个两孔插头的接口),而适配器则实现了这个接口,这样,对于使用者而言,其实他只知道自己在使用目标对象(即两孔的插座);同时,适配器也要具有被适配对象的能力(即使用三孔插座的能力)
在对象适配器中,利用组合的形式,将被适配对象作为适配器的一个属性,在调用相关方法的时候,实际上是被适配对象在调用它自身的相对应的方法。
好吧,其实说了那么多,还不如画个uml图来的实际:
以上就是对象适配器。另外再说一下类适配器,其类结构图如下:
由于在java中,类只能继承一个,所以说在java中实现不了
二. 外观模式
首先先聊一下什么是外观模式,刚开始看到这个模式的时候我以为是什么特别厉害的模式,可随着学习的深入,我才发现原来自己早就开始使用外观模式了,只是自己之前不知道怎么一回事。在effective java 一书中提到过,在工作中,尽可能的多使用组合,减少继承的使用次数,而外观模式,则是大量的利用了组合。
外观模式是指提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个更高一级的接口,让子系统更加容易的使用。
作用:为了简化接口,在提供简化接口的同时,依然将系统完整的功能暴露出来
举个简单的例子,以洗衣机为例:如今用洗衣机洗衣服一共需要几步?
1.把衣服放进去;2.倒上洗衣液;3.启动洗衣程序;4;将甩干的衣服拿出去晒了。
可是几年前的洗衣机就没那么只能,第三步需要加入人为的干预,例如将洗好的衣服放到另一个滚筒里甩干。
所以洗衣程序就是那个更高一级的接口,负责接管底下子系统的功能,减少人工干预。
这也让我想起了工作中遇到的一件事:之前在开发一项功能的时候需要使用产品客户端的cookie,为了防止每一次要用到cookie的时候都去申请一遍,我的一位前辈就让我将cookie值存到缓存中,实现并不复杂,刚开始的设计就是我去申请cookie,然后存到缓存中,其他人调用从缓存中获取cookie的方法,如果cookie获取不到,或是失效了,他们再调用我写的申请cookie的方法,结果我将这个方案提出来后就被否决了,前辈给出了两个意见:
1.先写接口,不要一开始就直接实现;2.只需要给我一个方法就行,调用者不需要去关心cookie拿不到的问题,所有工作都在内部实现。
现在想来这不就是外观设计模式吗,提供一个更高一级的接口,提供调用方法,调用者不需要操心底层的实现。
三. 两计模式的比较
适配器模式:其功能是将一个不满足客户需求的接口,转换为一个用户可以正常使用的接口,适配器可以将 一个或多个类接口变为一个所需要的接口(不一定说一个适配器对应一个要适配的类)
外观模式:其功能是为功能繁杂的子系统提供一个简化的接口。
装饰者模式:其是将一个对象包装起来以增加新的行为,但是无法在原有接口的基础上改变接口的相关功能。
上一篇: python读取测试数据的多种方式
下一篇: React(v16.8.4)生命周期详解