继承,一个父类可以有多个子类。父类就是把一些通用的代码放进去,然后在实现其他子类的时候少写一些代码。代码重用,很多人认为继承是一个极好的解决方案。如果将继承理解为代码重用,更多的是从子类的角度。使用客户端代码时,面对的是子类。这种继承称为实现继承:Childobject=newChild();还有一种看继承的方式:从父类往下看,当客户端使用的时候,面对的是父类,这种继承叫做接口继承:Parentobject=newChild();但是接口继承与多态性更相关。本文重点介绍实现继承。不推荐实现继承:?继承非常宝贵。Java只支持单继承。一个类只能有一个父类。一旦继承位置被实现继承占据,接口继承就很难做。受设计语言限制的思路是多语言,不使用继承,有代码复用的解决方案1、案例产品报表服务,服务之一:查询产品信息。这个查询过程是通用的,其他服务也可以。所以,我把它放在父类中复用:classBaseService{//获取对应的商品信息protectedListgetProducts(Listproduct){...}}//生成报表服务类ReportServiceextendsBaseService{publicvoidreport(){Listproduct=getProduct(...);//生成报表...}}ReportService没有继承任何类,但是代码也可以复用,即ProductFetcher模块。这样,如果我需要一个获取产品信息的地方,它不一定是服务,也不需要从任何类继承。获取商品信息和生成报表是两个东西,只是因为在生成报表的过程中需要获取商品信息,所以它有一个基类。无继承实现:classProductFetcher{//获取对应的商品信息publicListgetProducts(Listproduct){...}}//生成报表服务类ReportService{privateProductFetcherfetcher;publicvoidreport(){Listproduct=fetcher.getProducts(...);//生成报告...}}这是组合:一个ProductFetcher组合在ReportService中。设计通用原则:组合优于继承。也就是说,如果一个解决方案可以同时使用组合和继承来实现,那么就使用组合。那么,在写继承实现代码复用的时候,问问自己,这是接口继承,还是实现继承?如果实现继承,是否可以写成组合?2、面向组合编程的根本原因:获取产品信息和生成报表服务是两件事(关注点分离)。如果你看到两件事,你不会把它们放在一起。分解是设计的第一步,分解粒度越小越好。当可以分解多个关注点时,每个关注点都是一个独立的类。最后的类是由这些小类组合得到的,即面向组合的编程。面向组合的思想:为了增加复杂度,增加一个报表生成器(ReportGenerator),在获取商品信息后生成报表:classReportService{privateProductFetcherfetcher;私有ReportGenerator生成器;publicvoidreport(){Listproduct=fetcher.getProducts(...);//生成报告generator.generate(product);}}OOP适用于“对象”,而不是类!很多程序员习惯将对象理解为类的附属物,但在AlanKay的理解中,对象本身就是独立的个体。所以,有些语言支持直接操作对象。现在,我想为报表服务添加一个接口:处理产品信息。这样的处理只会影响这里的一个对象,而同一个ReportService的其他实例则完全不会受到影响。?好处不用写那么多类,程序运行时可以根据需要组合不同的对象。Java只有类的组织方法。因此,许多不同的概念只能用类的概念来表达。思维是有限的,不同的语言提供不同的表达形式,让概念更清晰。前面只是组合编程思维方式的改变,现在来看设计差异。3Case字体要求:支持粗体、下划线、斜体(Italic),可以任意组合。3.1继承需要8个类:3.2组合字体类(Font)只需要三个独立的维度:是否加粗、下划线、斜体。如果再有需求,变成4种,使用继承,类的数量扩展到16个,组合只需要再增加一个维度。将M*N问题和设计转换为M+N。Java在面向组合编程方面薄弱,但Java正在尝试不同的解决方案。早期的尝试包括Qi4j,后来Java8增加了默认方法,一定程度上也可以支持面向组合的编程。4、DCI继承是OOP原则之一,但是在编码实践中,可以尽量使用组合。DCI也是一种编码规范,是对OOP的补充,核心思想是关注点分离。DCI是对象数据data的缩写,是对象使用的上下文场景,以及对象的交互行为。是一种特别关注行为的模式(对应GoF行为模式)。用演员场景表演来解释,一个实体在某个场景中扮演包公的角色,执行包公盛唐的行为;一个典型的例子是银行账户转账,很难按照DDD划分账户对象。它是两个账户实例之间的行为,可以看作是转账场景中的账户实体(PPT,见四色原型),实现了转账行为。这个新的角度更贴近需求和自然,四色原型DDD和DCI的结合一步到位。将需求快速分解为可执行代码,是国际软件领域的一场革命。摘自https://www.jdon.com/dci.html5.总结组合优于继承。重用方法背后的编程思想:面向组合的编程。它给了我们一个不同的视角,但是支持面向组合编程的是关注点分离。将不同的关注点分开,每一个关注点都成为一个模块,需要的时候可以组装起来。面向组合编程,设计本身就有很多优秀的特性,可以降低程序的复杂度,改变思路。另见?https://www.infoq.cn/article/2007/11/qi4j-intro?https://en.wikipedia.org/wiki/Data,_context_and_interaction