在面向对象“设计原则”里面,有提到“尽量使用组合,聚合来代替继承”,这个好处是什么?
我感觉差不多啊,

解决方案 »

  1.   

    比如要设计“人”的类。
    用继承的话,得用基本人类都有属性作为父类。
    “男人”、“女人”分别给添加人xingqiguan属性。
    要是设计“人妖”、“天生残疾”呢?如果基类设计的不好这个时候就得改设计方案了。如果把qiguan都作为一个类,新建其他类型的“人”,直接往上面添加就的。残疾人少加点,男人多加点,人妖再多加点。
      

  2.   

    聚合是不是通过接口来实现?如果我改造windows控件使之具有另外一个接口,但是接口中的代码是一样的,是不是我要把windows控件都重写一遍啊?因为接口必须实现代码,有没有更好的办法?
      

  3.   

    设计叫做“设计原则”?我不太清楚你指的是哪一个流派的东西。在15年前写《设计模式》这本书的时候,基本上是散播java编程的高峰,而敏捷开发技术(甚至XP开发技术)以及随之时髦的“面向对象设计原则”还没有正式出现。所以,如果你把这个所谓的“设计原则”当作后来出现的“面向对象设计原则”,那么就会上当受骗了。如果不能看看java的类库,那么就看看.net的类库吧!你认为其使用的继承、接口“很少”吗?所以,看看实际的java、.net类库设计,你就可以少上这句话的当!关键是恰当地设计原则,而不是含沙射影地设计原则。所以面向对象设计的11条原则中都是实实在在的原则,而不是你所说的这种所谓的模糊的原则。
      

  4.   


    不是!从系统设计上,接口也是继承的一种形式,class跟interface是不用区分的。所谓组合,是指仅仅在属性、事件、方法上使用其它类型,而不是在自身类型定义上声明。
      

  5.   

    多说一句废话,一定要分清继承class和继承interface的不同,不要被误导了。虽然class和interface在被继承有很多相似的地方,但它们间有质的区别。继承class表示两个事物本质上是同一的,“本质”指它们确实是同一种类的东西。使用类继承要注意里氏替换原则。
    继承interface仅仅表示事物的行为是同一的,不要求两个事物本质相同。interface仅仅是个行为契约,约束范围比class要弱。两个事物行为同一时,本质不一定同一。例如:石墨可以写字,小刀也可以刻字,这说明它们具有相同的行为,可以继承同一个interface。但若要论本质,石墨本质上是一种矿石,应该去继承矿石基类,小刀本质上是一种工具,应该去继承工具基类,不能混淆。
    两个事物本质同一时,行为也不一定同一。例如:石墨和钻石本质上都是矿石,都继承自矿石基类,但石墨可以在纸上划字,所以可以继承“写字interface”,但钻石没法在纸上划字,就不能继承这个接口。
      

  6.   

    from wikipedia:Design patterns gained popularity in computer science after the book Design Patterns: Elements of Reusable Object-Oriented Software was published in 1994 by the so-called "Gang of Four" (Gamma et al.). Java is a programming language originally developed by James Gosling at Sun Microsystems (which is now a subsidiary of Oracle Corporation) and released in 1995 as a core component of Sun Microsystems' Java platform.
      

  7.   

    somthing found in the preface of GOF:
      

  8.   

    我干了两年java开发,不知道什么是聚合,组合
      

  9.   

    无来由的讨厌这种论调实际上我们不会说啥什么优于什么。情况总是相对滴,在简单系统里我们去面对对象自然不可避免继承而在复杂系统,我们也绝对不可能把所有的对象都放在一个体系里(除了object这个超类)so,这句话根本就是多余滴,在我看来这句话唯一目的是告诫程序员,这个世界上有一个object超类就够了,别总想着把所有东西都放在一个箱子里,那是God做的事情,而作为Human Being我们只不过是尽量地把东西按条理区分放置,然后按需求把他们组合起来
      

  10.   

    可以在纸上划字,所以只能继承“写字interface”而不能继承“写字class”吗?那么比如说我们做一个“外贸订单”的Winform控件,显然我们只能继承自Form类或者UserControl类,而只能让让它继承自“I订单”接口好用于系统的所有订单插件。这是不是说外贸订单的本质就不是订单,而是winform控件?我们知道这种所谓的经规定过头了,变成无意义的了。类似的有无数。比如我们为了使用Remoting,于是不得不让一些核心对象从MarshalByRefObject继承,于是我们就只能interface来表达业务继承了。这根本不是“本质与非本质之争”。面向对象有其原则,也有其实用。假设一个石墨产品就是一个可写字的产品,那么管它什么“写字class”还是“写字interface”,哪一个是本质哪一个不是?难道说只有从原子、分子的组合角度来说继承才叫做本质继承?愚蠢地把每一个单独的行为操作作为接口是很愚蠢的(这才是滥用继承),不知道接口只要符合“面向对象的11个原则”就可以实用起来则是毫无原则地使用接口。
      

  11.   

    愚蠢地把每一个单独的行为操作作为接口是很愚蠢的(这才是滥用继承),但是说class只能是“本质继承”也只是纯粹机械组合地来理解继承的。
      

  12.   

    “尽量使用组合,聚合来代替继承”这句话,或者说这类话,其实都是毫无尺度的。什么叫做“尽量”?这就等于暗示一些初学者“从不”,所以不管GOF(四人帮)弄出来说这句话的目的如何,我们知道它跟java、dor net类库以及之后的无数框架系统都只是似是而非地相关,因为GOF也许根本不懂如何讲明白“尽量”这个词的意义!而我们看“面向对象11条原则”,都是有具体测试的定性标准的。因此它用不着含沙射影地用“尽量”这个词,于是初学者也就真正才能行动、而不是争吵。
      

  13.   

    不过这个可以先不提。说一些人效率低得离谱,跟这个题目没有关系。题目中的这个说法,是出自16、17年前的GOF,这里只是分析这句话是否可以作为设计原则。
      

  14.   

    能够用UML画几个类图,然后用箭头连起来就是架构师了,呵呵
      

  15.   

    嗯,我想对于上面的“本质继承”再说一下。面向对象继承并不需要强调是非,更不需要大声说服别人什么是“本质”。其实面向对象的11条原则中的前3条就很明确了。比如说“里氏替换”原则。我们假设做一个关于“订单”的系统,那么所有针对订单接口(或者说订单类)的插件,我们可以随时用来测试任意一个具体类型的订单。假设设计了一个“i可写字”的接口,那么就要有一些列测试用例,并且这些测试用例可以用来测试以后的所有具有此接口的对象,遇到任何bug都应该停下手头所有工作来解决bug,而不是带着bug继续“开发”。面向对象11条原则被作为推广敏捷宣言的方法来提出,而不是作为当初推广java时搞得宣传手段,是有其必然性的。因为敏捷宣言提倡的是:用测试来说了算,而不是强调是非,不是强调什么是本质什么不是。
      

  16.   

    来这里学习
    呵呵
    头五项原则是关于类设计的,它们是: SRP,单一职责原则,一个类应该有且只有一个改变的理由。 
    OCP,开放封闭原则,你应该能够不用修改原有类就能扩展一个类的行为。 
    LSP,Liskov替换原则,派生类要与其基类自相容。 
    DIP,依赖倒置原则,依赖于抽象而不是实现。 
    ISP,接口隔离原则,客户只要关注它们所需的接口。 
    另外的六项是关于包的设计原则。在本文中,包是指一个二进制的可发布文件,比如.jar文件、或dll文件,而不是Java包或是C++的命名空间(译注3)。 头三项包原则是关于包内聚性的,它们会告诉我们该把什么划分到包中: REP,重用发布等价原则,重用的粒度就是发布的粒度。 
    CCP,共同封闭原则,包中的所有类对于同一类性质的变化应该是共同封闭的。  
    CRP,共同重用原则,一个包中的所有类应该是共同重用的。 最后的三项原则是关于包之间的耦合性原则的,并且论述了评价系统中包结构优良与否的评判标准。 ADP,无环依赖原则,在包的依赖关系图中不允许存在环。 
    SDP,稳定依赖原则,朝着稳定的方向进行依赖。 
    SAP,稳定抽象原则,包的抽象程度应该和其稳定程度一致。 
    译注: 1,OOD,全称Object Oriented Design,即面向对象设计。 2,PPP,即Bob大叔的著作《敏捷软件开发 原则、模式与实践》一书以及其相关书籍,因都有“原则、模式与实践”,即Priciples, Patterns and Practices,故常简称为PPP。 3,命名空间,原文为namespace,也译作名字空间。它是一种特殊的作用域,它包含了处于该作用域内的所有标示符,且本身也用一个标示符来表示,这样便于将一系列在逻辑上相关的标示符用一个标示符来组织。就Java编程语言来说,命名空间是通过java包来表达的,所有代码都归属与一个包。来自其他包中的代码要通过指定包名来引用某项特定的标示符,例如,包java.lang中的String类要通过java.lang.String的形式引用。在C++中,命名空间常用来避免命名冲突,尽管现今的C++语言对命名空间做出了扩展,但过去的C++代码很少使用此项功能。 
      (原文链接网址:http://www.butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod; Robert C. Martin的英文blog网址: http://www.butunclebob.com/ArticleS.UncleBob) 作者简介:Robert C. Martin是Object Mentor公司总裁,面向对象设计、模式、UML、敏捷方法学和极限编程领域内的资深顾问。他不仅是Jolt获奖图书《敏捷软件开发:原则、模式与实践》(中文版)(《敏捷软件开发》(英文影印版))的作者,还是畅销书Designing Object-Oriented C++ Applications Using the Booch Method的作者。Martin是Pattern Languages of Program Design 3和More C++ Gems的主编,并与James Newkirk合著了XP in Practice。他是国际程序员大会上著名的发言人,并在C++ Report杂志担任过4年的编辑。 
      

  17.   

    这些仅仅是.NET的游戏规则(Java也是这套规则),但这和面向对象无关...设计模式也只是工程方法的一些总结,是要随发展而变化的...真没什么好说的,还是那句老话...GoF的本意不是做八股文章,你们非要当八股文读那是你们的事儿...
      

  18.   

    所谓的这些原则,我一个都不知道,只知道面向对象有三大基本特征,继承、封装、多态。这三个是公认的面向对象的开发原则也是围绕这三个特征展开的。而设计模式,作为一个java程序员来说,在框架满天飞的今天,java早已淡化了设计模式的观念,struts+spring+hibernate(或其他ORM)的整合框架几乎干掉了所有设计模式。.NET这边,估计微软已经把设计模式也封装的快差不多傻瓜式操作了。所以现在讨论设计模式、设计原则的什么基本上没啥意义。面向对象开发的根本是让人们更容易用自然语言的形式去组织软件开发流程,过多的关注只有专业人员能看懂的设计模式、设计原则反而违背了面向对象开发的初衷。
      

  19.   


    “继承、封装、多态”作为原则是上个世纪80年代后期的事了。lz的问题里谈的GOF所给出的这个观念,是上个世纪90年代的事。而面向对象设计的11条原则则是代表着上个世纪最后2年的事,那个时候过分玩UML图也已经被广泛批评,于是才出现了敏捷开发。
      

  20.   

    不具体看Robert C. Martine提出的后边6条原则了。说说背景。我们都知道,在上个世纪80年代后期,面向对象技术分为三大流派:Booch、OMT和OOS。其中OMT方法最为成熟和一致,可以说没有它的奠基就不可能有统一的UML。然而UML的出现很大程度上跟Rational公司的商业和技术的巨大成功有关,这个公司也收编了OMT的创始人OOS的创始人,成为自己公司的员工。Rovert C. Martine是Booch方法的忠实传播者,也是Rational公司的员工,所以虽然他随后在面向对象系统分析和设计方面非常出名,但是其技术流派早期一直是Booch的。因此,他所画的UML图中,总是把方法当作对象类来处理,而不是像OMT那样去做比较纯粹的OOAD分析和设计。但是在20世纪后期,Martine转向XP了。不过他获得极高声誉的《敏捷软件开发:原则、模式与实践》这本书中其实还是大量用了他转向XP之前的许多年准备写UML的书的资料,所以这一本书并不是敏捷开发的正宗教材,而是还是有很多繁冗的跟这本书的书名、目的不太相符东西。其中,所谓面向对象11条原则的后6条,就有明显的这些特性。
      

  21.   


    谢谢sp1234通过反问的形式提醒我的疏漏。在9楼我说了要区分事物本质,注意里氏替换原则,却漏了说明非常重要的一点:区分事物本质是要考虑事物所处的环境。因为以不同的观点看同一个事物,也会得到不同的结果。
    例如开发一个鸵鸟和鸟的系统,如果这个系统是用来考察鸟类的羽毛,鸵鸟自然应该继承鸟基类。但若系统是用来考察鸟类的飞行速度,很自然,鸵鸟就不适合继承鸟基类了,它根本就不会飞。
    借用一下sp1234先生的例子,在外贸订单系统中,如果能区分出考察“外贸订单”的环境,就不会迷惑了:在系统的业务逻辑层,“外贸订单”就是属于一类订单,因为在这层要处理订单的现实逻辑关系。而在系统的展示层,“外贸订单窗体”本身不是“订单”,本质上讲它是用来展示订单数据的界面,这样它继承Form类也就是很自然的事情了。如果非让“外贸订单窗体”继承一个接口的话,它不应该继承“I订单”接口,而应该继承“I显示订单”接口。系统业务层考察订单的现实逻辑,系统展示层考察订单的显示逻辑,考察视角的不同,结果“外贸订单”是系统的两个层里面大不相同。所以设计系统里的类时,要注意根据系统的使用范围判断类的继承逻辑,如果一个系统不是考察分子、原子的组合,那么就不应该从物质物理组成的角度区分事物本质。就算确定了系统范围,实现这个系统也会有多种方法,不会是“只能”这么做或“只能”那么做,要根据你面对的实际情况(比如你团队的技术实力等)做出最适合你的选择。另外,就算是真理也有适用范围,更何况我是无名小辈,说的话连真理都算不上。所以请楼主自己思考,万一我说的话有错,不要误导了楼主。再次感谢sp1234先生,及时指出了我的疏漏。
      

  22.   

    任何事物都有正反两面
    好处就是组合在扩展会更加灵魂(其代表就是策略模式 你还是看看<Head First设计模式>把)另外补充一下
    sp1234的观点不适合初中级别的人 他是更高层次的思维
    已经是"心中有刀 心中无刀"古龙小说里面所说的高手境界了
    但我们初中级别的还是练练招式把
    使用过才知道好坏 这个是一个必须的过程
    他总想把他十几年的功力传给我们 不考虑我们会不会消化不良
      

  23.   

    以下仅是一家之言:
    一、先纠正
    这条原则属于面向对象的设计原则二、关于楼主所提问题的答覆
    好处是更灵活,简化类的继承体系,减小设计的复杂度[这个需要仔细体悟],你可以以策略模式作为研究对象,它就是用的聚合,你想一下,如果用继承会怎么样,有哪些坏处。三、关于面向对象设计原则、设计模式、OOP之间的关系
    OOP三大要素是应用面向对象设计原则、设计模式的语言基础。它是OOPL所固有的。
    关于设计模式有一个重要的概念:模式不是一开始就有的,而是不断重构出来的。那么既然是重构出来的,那么是如何重构出来的呢?我们在重构时总有一个目标吧。不能看代码不顺眼就改。我们重构所根据的就是面向对象的设计原则。ok。有人看了Martin flower的《重构》,说:重构不是根据原则,而是根据一堆的方法。如重命名方法、上移方法、提炼类……
    那么这些方法的实质是要达到一个怎样的目标呢?就是面向对象的设计原则。ok。可能还有些词不达意。有很多想说的没说出来。