Facade和Adapter

设计模式是面向对象编程的精髓,本文主要介绍了两种常见设计模式——Facade和Adapter。Facade模式通过提供统一接口简化子系统,减少冗余代码,增强封装性和移植性。Adapter模式则解决接口不兼容问题,实现不同系统间的协同工作,是系统移植的通用解决方案。通过实例解释了两种模式在实际开发中的应用和区别。
摘要由CSDN通过智能技术生成

设计模式初探

设计模式有多么重要?身为在校学生,很少有人能有机会参与到真正的大型项目的设计中来,相信很多人在学习了C++和Java等面向对象的语言后,能够用面向对象语言提供的语法和特性设计一些程序并进行了一些实践后,就认为自己对面向对象有了一些体会。对于很多人来说,精通面向对象编程就等同与熟悉c++/java/等等其他的语法,对语法关注的程度要远远超过语言特性本身。我发现越是特别是有经验的C程序员,在学习C++时这种表现尤为明显。

最近学习设计模式,由于是零基础,在同学的推荐下,入手了被成为设计模式圣经的Gof所著《设计模式--可复用面向对象软件的基础》。虽然之前在课程上实践中也有过一些C++的使用经历,并且也曾经用C++完成过几个课程作业的开发,但是当看到这本书时还是觉得很难啃。我觉得原因在于两点:

一是这本书太过专业。这本书着重与将23种设计模式的适用环境和具体设计方法进行严谨,统一,细致的描述,这显然过于专业了,对于我这种没有进行过大型面向对象软件开发的“小白”来说,着实有点不会走就要学飞的感觉。

第二点原因,很明显,是我太菜。虽然使用过C++做过一些系统,并且也花了一些时间学习C++的语法和编程规范,但是不得不承认我其实对面向对象编程并没有实质的感悟。在笔者利用C++开发的几个系统中,对于对象的设计简直是糟糕透顶的。当然,在实施系统编码之前我也会对系统进行分析及对象建模,但是方法十分笨拙。我所做的就是从需求描述中提取里面的名词,将他们定义为类,然后从需求描述中提取动词,将这些动词定位到对应的类并定义为他们的成员变量。这种方法虽简单,却十分糟糕。回想一年前曾经使用C++写的一个五子棋对战程序,我就是采用这种方法,对后导致的后果是在程序开发越到后面时,麻烦越大,我总是在为一开始那些不良的设计埋单,总是为了实现一些新的功能或改写旧的功能做很多的walk around,最后整个程序虽然完成,但我自己的感觉依然是一大mess!我都很难想象如果再增加新的功能,会导致多大的烦恼!由此可见,一个良好的设计,是多么的重要。

所以我认为,面向对象的精髓,应该是设计模式!

当然GoF的书固然经典,但确实不是和我这样的入门学习者。经过一段时间在豆瓣的探索,很多人推荐入门看Alan Shalloway的《设计模式解析》。入手此书后,才发现它其实也不厚:-)。几天下来抽空看了几章,给我感触很大。和Gof不同的是,这本书并没有对各个设计模式进行详细的讲解与总结,而是在花很多篇幅告诉读者:我们为什么要设计模式?为什么模式会这样设计?什么样的面向对象设计才是优质的?不得不说,此书,真乃设计模式入门神做。作者将更多的精力集中在why,而不是how,而这,正是我这个入门者最急需的知识。

设计模式的作用,就是把面向对象设计中常见的问题和相应的最优解决总结出来,以给我们的对象设计提供前车之鉴和指导。是的,这就是人们时常所说的,“站在巨人的肩膀上”;站的更高,才能看得更远!这边文章中,我想对设计模式解析一书中讲到的前两个模式Facade和Adapter模式总结下。书中将这两个模式放在模式实例的最开始进行讲述,我相信是有很大理由的--他们很简单,而且非常常用。很多人就算没有学习过设计模式,在自己系统的设计中也会或多或少使用到。

Facade

“Facade”,e文里是“表面”,“前面”的意思。这个名字确实起的很传神~。

《设计模式》一书中对Facade模式的描述是:“为子系统中的一组接口提供一个统一接口。Facade模式定义了一个更高层的接口,是子系统更加容易使用”。看,这就是GoF,其实这个模式很简单,但是他总是试图用一些通用的方法去描述,让你初看时,云里雾里。

Alan书中一个简单的例子,顿时叫人明了了--其实Facade模式对于很多人都不陌生,哪怕你没有接触过设计模式,很多人在设计系统时或多或少会使用到这种思想。比如你在开发一个网购系统,系统中有买家,卖家、产品信息以及买卖双方之间的各种交易;我们会在数据库中定义相关的表格来存储这些信息,比如用户表,产品表,交易表。系统实施时,买家、卖家、系统都可能随时操作数据空中的相关表格,他们都遵循着一个统一的操作模式:打开数据库->执行SQL语句->验证结果->关闭数据库。于是乎我们想不如创建一个DatabaseManager类,只提供给用户他们感兴趣的一个统一的,简单的接口,而屏蔽掉这些实现细节。系统运行时我们构造这么一个管理类来满足各种数据库相关操作的请求。

Facade模式带来的优点是显而易见的:

1.减少了冗余代码,我们不必每次用相似的代码去完成相似的工作

2.更好的封装性,只提供给用户他们关心的接口,而用户不用去关心实现细节

3.更好的移植性,当我们的数据库系统更改时我们不必更改任何用户代码,只需要更改数据库管理类的实现代码。这也是Alan在书中提到的队封装的理解:“封装那些可能会变化的东西”。

Facade,很简单,也很常用。

Adapter

首先还是GoF,这是他们对Adapter的定义:“Adapter将一个类的接口转化为客户希望的另一个接口,使原本由于接口不兼容而不能一起工作的类能够一起工作。”

Adapater模式的存在,就是问了解决兼容问题,是系统移植的通用解决方案。想想我们的java语言。java语言的一大特色就是跨平台,用户可以一次编写,多次执行。java源代码首先被编译成字节码,这些字节码运行在java虚拟机上,而java虚拟机可以运行在不同的操作系统之上,而实现了“跨平台”。这样看来,java虚拟机就是一个巨大的Adapter。统一的字节码,经过JVM的“翻译”,变成可以各个平台上执行的程序流。JVM就像是用户代码和实际操作系统API之间的Adapter,它的存在让用户程序不用做任何更改即可运行在不同的系统之上。

再举一个例子,我近期的项目中也涉及到系统移植的问题。需要把lwIP(一个轻量级的TCP/IP协议栈的实现)移植到一个嵌入式实时系统上去。由于lwIP在协议栈的实现中,使用了许多依赖操作系统的系统功能,如信号量,内存管理,定时器,消息队列,网卡驱动等等。lwIP的设计者为了方便移植,将所有这些系统功能抽象成一套自己的API列表,并提供他所关心的功能和函数原型,lwIP的实现中所有对这些API的引用均采用这些函数;而移植者为了把协议栈移植到自己的系统上,只需要根据自己的系统API来实现这些统一接口就好。比如线程创建函数被lwIP同意定义为sys_thread_new(若干参数),移植者只需要将这个函数根据自己的系统API进行实现即可,比如在Linux上可能是pthread_create,在win下可能是CreateThread--不管是什么,lwIP都不care,你只要提供了正确的函数就行了。当然这是例子是面向过程的应用,在面向对象中,一样如此。

这样看来,Adapter和Facade看起来好像没什么区别了。貌似都是提供一层封装的接口给用户,便于用户使用。但是他们之间还是有区别的,只是相当微妙。

Facade着重于实现细节隐藏,而Adapter着重于移植。在实现上,他们都是用已有的老接口实现新的接口提供给用户,但是不同在于这个新的接口--Facade模式中新的接口也是Facade实现者自己定义的,而Adapter的实现着就没有这么大的权力了,因为他们提供的新接口必须满足一些现有的接口形式。

这就像你去餐厅吃饭,服务生问你吃什么。你可以说“随便,好吃就行”。这时餐厅的选择就很多了,只要给你好吃的就行,而具体是什么以及怎么做的,你不care---这就是Facade;而如果你说“我要牛排”,餐厅的选择就少了,他们所作的就是给你提供牛排,而牛排是怎么做的,你不care,你只要是牛排就行了---这就是Adapter。

总结一下:这两个设计模式虽然简单常用,但是作用也是不可小视的。虽然我们在解决实际问题中很多人都自然会用到这两个模式中提供的方法去设计,但是鲜有人总结出来。设计模式的作用就是将这些最常用并且行之有效的设计方法总结出来,让你的设计更加优质。设计模式的要点不在于单个模式的理解,而在于在实际系统中多个模式组合起来,灵活应用!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值