.NET设计模式(15):结构型模式专题总结

——探索设计模式系列之十五

Terrylee20065

摘要:结构型模式,顾名思义讨论的是类和对象的结构,它采用继承机制来组合接口或实现(类结构型模式),或者通过组合一些对象,从而实现新的功能(对象结构型模式)。这些结构型模式,它们在某些方面具有很大的相似性,仔细推敲,侧重点却各有不同。本文试图对这几种结构型模式做一个简单的小结。

 

主要内容

1.结构型模式概述

2.结构型模式区别与比较

3.对变化的封装

 

结构型模式概述

结构型模式,顾名思义讨论的是类和对象的结构,它采用继承机制来组合接口或实现(类结构型模式),或者通过组合一些对象,从而实现新的功能(对象结构型模式)。这些结构型模式,它们在某些方面具有很大的相似性,仔细推敲,侧重点却各有不同。

Adapter模式通过类的继承或者对象的组合侧重于转换已有的接口;Bridge模式通过将抽象和实现相分离,让它们可以分别独立的变化,它强调的是系统沿着多个方向的变化;Decorator模式采用对象组合而非继承的手法,实现了在运行时动态的扩展对象功能的能力,它强调的是扩展接口;Composite模式模糊了简单元素和复杂元素的概念,它强调的是一种类层次式的结构;Façade 模式将复杂系统的内部子系统与客户程序之间的依赖解耦,它侧重于简化接口,更多的是一种架构模式;Flyweight模式解决的是由于大量的细粒度对象所造成的内存开销的问题,它与Façade模式恰好相反,关注的重点是细小的对象;Proxy模式为其他对象提供一种代理以控制对这个对象的访问,它注重于增加间接层来简化复杂的问题。

结构型模式区别与比较

1.桥接模式与装饰模式

这两个模式在一定程度上都是为了减少子类的数目,避免出现复杂的继承关系。但是它们解决的方法却各有不同,装饰模式把子类中比基类中多出来的部分放到单独的类里面,以适应新功能增加的需要,当我们把描述新功能的类封装到基类的对象里面时,就得到了所需要的子类对象,这些描述新功能的类通过组合可以实现很多的功能组合,装饰模式的简略图如下:


图1  装饰模式简略图

桥接模式则把原来的基类的实现化细节抽象出来,在构造到一个实现化的结构中,然后再把原来的基类改造成一个抽象化的等级结构,这样就可以实现系统在多个维度上的独立变化,桥接模式的简略图如下:


图2  桥接模式简略图 

2.外观模式和代理模式

外观模式和代理模式解决问题的侧重点不同,但是它们解决问题的手法却是一样的,即都是引入了间接层的手法,这也是我们软件系统中经常用的一种手法。外观模式虽然侧重于简化接口,但是在某些情况下,外观模式也可以兼任代理模式的责任,例如外观对象有可能是另一个位于另一个地址空间对象的远程代理,这时候我们可以叫做外观代理模式,或者代理外观模式。它们的类简略图如下:

  图3  代理模式简略图


图4  外观模式简略图

3.适配器模式

适配器模式重在转换接口,它能够使原本不能在一起工作的两个类一起工作,所以经常用在类库复用,代码迁移等方面,有一种亡羊补牢的味道。类适配器和对象适配器可以根据具体实际情况来选用,但一般情况建议使用对象适配器模式,如下图所示,左边是类适配器模式,右边是对象适配器模式:


   图5  适配器模式简略图

对变化的封装

如何应对变化,是软件开发的一个永恒的主题,也许我们不能够杜绝变化的发生,但至少我们可以通过一些手段让变化降到最低。“找到系统可变的因素,将之封装起来”,通常就叫做对变化的封装。关于这个问题的解释在《Java与模式》中讲的很清晰,抽象化与实现化的简单实现,也就是“开-闭”原则在类层次上的最简单实现,如下图所示:


图6

在这个继承结构中,第一层是抽象化,它封装了抽象的业务逻辑,这是系统中不变的部分;第二层是实现化,它是具体的业务逻辑的实现,封装了系统中变化的部分,这个实现允许实现化角色多态性的变化:


图7

也就是说,客户端依赖的是业务逻辑的抽象化类型的对象,而与抽象化的具体实现无关,不在乎它到底是“实现化”,“实现化2”还是“实现化3”,如下图所示:


图8

每一种继承关系都封装了一个变化因素,而一个继承关系不应当处理两个变化因素,换言之,这种简单继承关系不能处理抽象化与实现化都变化的情况,如下图所示:


图9

上图中的两个变化因素应当是独立的,可以在不影响另一者的情况下独立的变化,如下面这两个等级结构分别封装了自己的变化因素,由于每一个变化因素都是可以通过静态关系表达的,因此分别使用继承关系实现,如下图:


图10

在抽象化和实现化之间的联系怎么办呢?好的设计只有一个,不好的设计却有很多中,下面这种设计就是继续使用继承进行静态关系设计的类图:


图11

这样的设计其实存在着很多的问题,首先出现的是多重的继承关系,随着具体实现化的增多,子类的继承关系会变得异常复杂;其次如果出现新的抽象化修正或者新的具体实现角色,就只好重新修改现有系统中的静态关系,以适应新的角色,这就违背了开放-封闭原则。正确是设计应该是使用两个独立的等级结构封装两个独立的变化因素,并在它们之间使用聚合关系,以达到功能复用的目的,这就回到了我们的桥接模式上,如下图所示:


图12

从另一个角度讲,一个好的设计通常没有多于两层的继承等级结构,或者说,如果出现两个以上的变化因素,就需要找出哪一个因素是静态的,可以使用静态关系,哪一个是动态的,必须使用聚合关系。

 

更多的设计模式文章可以访问《.NET设计模式系列文章

 

参考资料

Erich Gamma等,《设计模式:可复用面向对象软件的基础》,机械工业出版社

Robert C.Martin,《敏捷软件开发:原则、模式与实践》,清华大学出版社

阎宏,《Java与模式》,电子工业出版社

Alan Shalloway James R. Trott,《Design Patterns Explained》,中国电力出版社

posted on 2006-06-01 08:50 TerryLee 阅读(5547) 评论(19)  编辑 收藏 所属分类: Design Patterns

评论

#1楼  2006-06-01 17:24 SPARON      

呵呵,第一个来的哈,,,
今天无意中发现了TerryLee的设计模式系列,感觉讲得很好,所以全部下了下来,慢慢研究,在此由衷的感谢TL为大家无私的奉献!!!   回复  引用  查看    

#2楼 [楼主] 2006-06-01 17:53 TerryLee      

@SPARON

呵呵,谢谢支持:)   回复  引用  查看    

#3楼  2006-06-06 11:02 jyming [未注册用户]

篇篇关注!   回复  引用  查看    

#4楼 [楼主] 2006-06-06 11:30 TerryLee      

@jyming

呵呵,谢谢:-)   回复  引用  查看    

#5楼  2006-06-21 14:04 一汐      

很久没过来看你的文章了,今天来你家做客发现又多了不少东西

谢谢你的无私奉献精神,期待更加精彩的文章,加油:)   回复  引用  查看    

#6楼 [楼主] 2006-06-21 14:23 TerryLee      

@一汐
谢谢:-)   回复  引用  查看    

#7楼  2006-06-26 17:28 雨人      

期待更多文章   回复  引用  查看    

#8楼 [楼主] 2006-06-26 17:38 TerryLee      

@雨人
后面的文章还会继续:-)   回复  引用  查看    

#9楼  2006-07-02 09:56 星星远好 [未注册用户]

楼主,你的文章都写得很好,我很喜欢。在此表示非常感谢,但是我有一个想法想与你交流一下。
这文章提及的对变化的封装可以不可以理解为模板模式与桥接模式的综合呢?我是初学者,很多地方可能都理解不是很正确,请指教。
还有一点,文章提到好的设计只有一个,不好的设计却很多,这句话我不认同。
我认为现在的软件设计都是不好的,只不过人们还没有发现更好的,就只能用不好的设计了。我认为改为没有最设计,只有更好设计。   回复  引用  查看    

#10楼 [楼主] 2006-07-02 10:29 TerryLee      

@星星远好
1.这篇文章中的对变化的封装,其实是以Bridge模式的演化来说明的,在这儿并没有涉及到Template Method模式,至于在实际应用中是否可以结合,则根据实际情况而定;

2.对于这个问题,只是说在这种需求下,不好的设计却有很多,另外现在的软件设计也不是都是不好的,这好像打击面大了些,相对较好就可以了。   回复  引用  查看    

#11楼  2006-07-04 08:27 stonezhu      

等的急啦,继续写下去啊~~:)很喜欢看你的文章,写的很好,很有思路.   回复  引用  查看    

#12楼 [楼主] 2006-07-04 09:28 TerryLee      

@stonezhu

呵呵,我知道大家等的着急,实在对不住大家。其实我自己也很着急

可是最近总是没有思路,写出来总感觉不尽人意,有几篇我还得修改一下,过几天发上来:)   回复  引用  查看    

#13楼  2006-07-04 10:57 stonezhu      

:)谢谢,谢谢...你的文章思路还是很清晰的,喜欢的你的文章.   回复  引用  查看    

#14楼 [楼主] 2006-07-04 18:18 TerryLee      

@stonezhu

今天更新了一篇,Template Method模式   回复  引用  查看    

#15楼  2006-08-24 11:45 joyli [未注册用户]

总结的好!支持一下!   回复  引用  查看    

#16楼  2006-09-23 17:20 小芒果先生      

支持   回复  引用  查看    

#17楼  2007-05-11 16:15 尹秀文 [未注册用户]

写得非常好!多谢了!!   回复  引用  查看    

#18楼  2008-01-16 14:01 tianyamoon      

好文章总得称赞下。   回复  引用  查看    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2006-06-01 13:04 编辑过
 
另存  打印
最新IT新闻:
· 阿里巴巴确立未来十年战略规划 修改自身定位
· 微软高管:Wii用户最终会成为Xbox 360用户
· 遵守YouTube案裁定 谷歌将陷入隐私指控深渊
· iPhone入华在即 中国手机产业生存面临考验
· 阿里巴巴集团再向淘宝注资20亿元
 


导航

公告

  • 网名:TerryLee
  • 本名:李会军
  • 位置:中国北京 Ethos
  • 联系方式:
  • 个人主页

 MVP配置

 版权声明

  • 本站采用创作共用许可 署名,非商业

绿色通道

IT新闻

统计

与我联系

留言簿(311)

我的标签

随笔分类

随笔档案

个人站点

关注项目

好的网站

我的好友

友情博客

搜索

积分与排名

阅读排行榜

评论排行榜