七     月     天
     本站首页    管理页面    写新日志    退出


«July 2020»
1234
567891011
12131415161718
19202122232425
262728293031


公告
暂无公告...

我的分类(专题)

日志更新

最新评论

留言板

链接


Blog信息
blog名称:七月天
日志总数:19
评论数量:84
留言数量:0
访问次数:182863
建立时间:2004年11月4日




[设计模式]设计模式(8)--采用委托减少继承的使用(原则2)
原创空间,  读书笔记,  软件技术

torrent 发表于 2005-8-16 16:20:33

让重用机制发挥作用   多数人能够理解对象、接口、类、继承等概念。然而,真正的挑战在于应用这些概念来构建灵活、可重用的软件。设计模式告诉你如何做到这一点。   继承VS合成   在面向对象系统的功能重用过程中,两个最普遍的技术就是类的继承和对象合成。我们之前解释过,类的继承让你能通过某个类的实现定义另外的类的实现。通过子类实现的重用通常指“白盒重用”。术语“白盒”指的是可见性:通过继承,父类的内部结构对子类来说是可见的。 对象合成是类继承的替代选择。通过汇编或合成对象可以获得新的功能。对象合成需要用来进行合成的对象具备良好定义的接口。这种类型的重用被称为“黑盒重用”,因为对象的内部细节是不可见的。   继承和合成都有各自的优缺点。类的继承是在编译时静态定义的,且由于语言的直接支持,可直接实现。类继承也使得可以较易的在重用时修改实现,当子类重载部分而不是所有的操作时,它同样可影响其继承而来的操作(在使用了重载的情况下)。 类继承也有一些缺点。首先,由于继承在编译时完成,因此,不可能在运行时改变继承自其父类的实现;其次,更糟的是,父类通常定义了其子类的部分物理表示。因为继承向子类暴露了父类的实现细节,故有这样的说法—继承打破封装。因为子类的实现与父类的实现关系密切,所以父类实现的任何改变将引起子类的变化。 当你试图重用一个子类时,这种实现依赖可能会产生问题,由于通过继承得到的实现不可能在每个方面都适合新的问题领域,故父类可能会要更改或重写。这种依赖限制了灵活性,并最终限制了可重用性。解决的方案是仅仅通过抽象类来继承,因为抽象类通常提供很少的实现、甚至根本没有任何实现。   对象合成是对象通过获得其他对象的引用,而在运行时动态完成的。合成需要对象表明各自的接口,这需要小心的设计接口,以利对象可与其他更多对象一起使用。因为对象通过其接口进行访问,我们不必打破封装。只要拥有同一类型,任何对象都能在运行时替换为另外的对象。而且,因为对象的实现是根据其接口而编写,这将减少实现依赖。 对象合成在系统设计中还有另外一个效果。任用对象合成能帮助你保持类的封装而可专心处理一项任务。你的类和类层次将保持较小,很少出现变成难以管理的层次大怪。另一方面,基于对象合成的设计中将拥有更多的对象(在更少的类的情况下),系统的行为将决定于它们之间的相互关系,而不是在一个类中定义。 这里导出了我们的第二个面向对象设计原则:   优先采用对象合成来代替类继承   理想情况下,你应该在不必编写新组件的情况下达成重用,你应当可以通过对象合成来组装存在的组件而得到所需的功能。但这种情况很少,因为在实践中可获得的组件集并不十分丰富。 根据我们的经验,设计中采用继承作为重用技术的情况有些过滥,其实,在设计中更多的任用对象合成技术将带来更好的可重用性。在设计模式中,你将看到一次又一次的对象合成应用。   委托   委托是使得合成技术在重用中完成和继承一样功能的一个办法。在委托中,当处理请求时,涉及到两个对象:接收者对象委托其操作给委托人对象(代表)。一个类比是子类处理发给父类的请求。但是,在继承中,继承而来的操作总可以通过this成员变量指向接收者对象;而在委托中,为了达成同样的效果,接收者将自己传递给委托人,以让被委托的操作指向接受者。 例如,代替将窗口类作为矩形类的子类的方案,窗口类可以通过保持一个矩形实例变量,并将矩形的详细行为委托给它,而重用矩形类的行为。换句话说,“窗口是矩形”的替代方案是,“窗口可以作为一个矩形”。应用委托,窗口对象可以明确的发送请求给其矩形对象实例;而如果不采用委托,它可能必须继承这些操作。   委托的主要优点在于,可以容易的在运行时合成(compose)行为并改变其合成方式。假设矩形类和圆类拥有同样的类型,我们的窗口可以在运行时变成圆,只需通过用圆实例替换矩形实例。   委托与其它通过对象合成来增强软件灵活性的技术一样,都有一个共同的缺点:动态、高参数化的软件与相对静态的软件相比,比较难以理解。另外,委托也存在运行时效率问题。只有当运用委托的简化性超过其复杂性的情况下,委托才是一种好的设计选择。很难说明何时运用委托,因为其效率取决于其应用环境,而对效率的判断取决于设计者运用它的经验。最好的应用委托的情况是当它运用于高度程式化的环境----即,在标准模式中。   有几个设计模式应用了委托,如状态模式、策略模式、和访问者模式。在状态模式中,一个对象委托其请求给状态对象,状态对象表示了它的当前状态;策略模式中,一个对象委托一个详细请求给另外一个表示携带请求的策略的对象;一个对象只有一个状态,但可以有多个针对不同请求的策略,这两个模式的目的都是为了通过改变委托请求的对象,而改变对象的行为。在访问者模式中,对对象结构的每一个元素的执行操作总是委托给了访问者对象。 在其他的模式中委托的应用,没有在上述模式中那么重要。解调器模式用一个对象去协调其它对象的通信,解调器对象有时简单的直接用其它对象执行操作,有的时候,它提交一个对自身的引用,此时真正运用了委托;责任链对象通过将请求沿着对象链从一个对象传到另外一个,从而处理请求。有时,请求携带了一个接收请求的原始对象的引用,此时,该模式运用了委托;桥接模式分离了实现与其抽象,当抽象和特定实现匹配时,抽象可简单的委托对具体实现的操作。   委托是对象合成的一个特例。这说明,为了代码重用,总能用对象合成机制来替换继承。


阅读全文(5269) | 回复(-1) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.031 second(s), page refreshed 144422341 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号