软件设计之美
郑晔
推文科技技术VP,前火币网首席架构师
立即订阅
3313 人已学习
课程目录
已更新 30 讲 / 共 36 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 软件设计,应对需求规模的“算法”
免费
课前必读 (3讲)
01 | 软件设计到底是什么?
02 | 分离关注点:软件设计至关重要的第一步
03 | 可测试性: 一个影响软件设计的重要因素
了解一个软件的设计 (4讲)
04 | 三步走:如何了解一个软件的设计?
05 | Spring DI容器:如何分析一个软件的模型?
06 | Ruby on Rails:如何分析一个软件的接口?
07 | Kafka:如何分析一个软件的实现?
设计一个软件—程序设计语言 (5讲)
08 | 语言的模型:如何打破单一语言局限,让设计更好地落地?
09 | 语言的接口:语法和程序库,软件设计的发力点
10 | 语言的实现:运行时,软件设计的地基
11 | DSL:你也可以设计一门自己的语言
加餐 | 再八卦几门语言!
设计一个软件—编程范式 (9讲)
12 | 编程范式:明明写的是Java,为什么被人说成了C代码?
13 | 结构化编程:为什么做设计时仅有结构化编程是不够的?
14 | 面向对象之封装:怎样的封装才算是高内聚?
15 | 面向对象之继承:继承是代码复用的合理方式吗?
16 | 面向对象之多态:为什么“稀疏平常”的多态,是软件设计的大杀器?
17 | 函数式编程:不用函数式编程语言,怎么写函数式的程序?
18 | 函数式编程之组合性:函数式编程为什么如此吸引人?
19 | 函数式编程之不变性:怎样保证我的代码不会被别人破坏?
加餐 | 函数式编程拾遗
设计一个软件—设计原则与模式 (7讲)
20 | 单一职责原则:你的模块到底为谁负责?
21 | 开放封闭原则:不改代码怎么写新功能?
22 | Liskov替换原则:用了继承,子类就设计对了吗?
23 | 接口隔离原则:接口里的方法,你都用得到吗?
24 | 依赖倒置原则:高层代码和底层代码,到底谁该依赖谁?
25 | 设计模式:每一种都是一个特定问题的解决方案
26 | 简单设计:难道一开始就要把设计做复杂吗?
设计一个软件—设计方法 (1讲)
27 | 领域驱动设计:如何从零开始设计一个软件?
软件设计之美
15
15
1.0x
00:00/00:00
登录|注册

15 | 面向对象之继承:继承是代码复用的合理方式吗?

郑晔 2020-06-29
你好!我是郑晔。
上一讲,我们讨论了面向对象的第一个特点:封装。这一讲,我们继续来看面向对象的第二个特点:继承。首先,你对继承的第一印象是什么呢?
说到继承,很多讲面向对象的教材一般会这么讲,给你画一棵树,父类是根节点,而子类是叶子节点,显然,一个父类可以有许多个子类。
父类是干什么用的呢?就是把一些公共代码放进去,之后在实现其他子类时,可以少写一些代码。讲程序库的时候,我们说过,设计的职责之一就是消除重复,代码复用。所以,在很多人的印象中,继承就是一种代码复用的方式。
如果我们把继承理解成一种代码复用方式,更多地是站在子类的角度向上看。在客户端代码使用的时候,面对的是子类,这种继承叫实现继承:
Child object = new Child();
其实,还有一种看待继承的角度,就是从父类的角度往下看,客户端使用的时候,面对的是父类,这种继承叫接口继承:
Parent object = new Child();
不过,接口继承更多是与多态相关,我们暂且放一放,留到下一讲再来讨论。这一讲,我们还是主要来说说实现继承。其实,实现继承并不是一种好的做法。
也就是说,把实现继承当作一种代码复用的方式,并不是一种值得鼓励的做法。一方面,继承是很宝贵的,尤其是 Java 这种单继承的程序设计语言。每个类只能有一个父类,一旦继承的位置被实现继承占据了,再想做接口继承就很难了。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《软件设计之美》,如需阅读全部文章,
请订阅文章所属专栏新⼈⾸单¥19.9
立即订阅
登录 后留言

精选留言(10)

  • Jxin
    1.链接打不开,应该要翻墙,回家再看。
    2.DCI和小类大对象的理念,在实现手法上很像。
    3.先说看好的点,DCI模式在单一职责上能做到更好(ddd的充血模型很容易肿成上帝对象)。一个data在不同的context具有不同的interface方法,这样的划分,在隔离变化(调用方依赖抽象接口实现功能)和复杂性隔离(只关心当前context需要关心的行为)都又不错的效果。
    4.再说不看好的,DCI的数据和行为分离不敢苟同。是先有行为再有数据还是先有数据再有行为,这是一个问题。但可以确定的是,行为和数据的关联是密切的,以至于傻傻分不清楚。所以我还是偏向于,抽象模型时,行为和数据应该是一个整体。

    5.总结,DCI还是扩展了我的认知。DDD在封装充血模型时有一个很蛋疼的点,为了复用部分属性和行为,而为充血模型加入了新的属性和行为。多次迭代后,充血模型就很容易肿大,边界模糊(涵盖的面广了也就模糊了)。而DCI和小类大对象的思考方式很好的做了补充。大致都是在特定的context里,用不同的小类组成特定的领域对象,既能做到复用也能隔离复杂性。
    6.C++有多继承的方式来实现这种组合模式。但java语法特性上就不支持。那么无论是小类大对象还是DCI都无法用合适的代码结构来描述(我认为,哪怕用回调函数+接口实现的写法,也不能很好描述这个语义)。栏主觉得java该怎么办?
    2020-06-29
    8
  • Being
    老师,我有个概念上的疑惑,分离的关注点是一个个独立的模块,然后由一个个小模块组合出类,这个类就指的是“大对象”吗?
    上面的一个个小模块,其实也是类,只不过是小类,对于C++就是class的实现手法,Ruby可以是module的实现手法,是这样的吗?

    DCI关注的是数据在context中的交互行为,我的理解大概就是数据在不同的context,扮演不同的角色,这些角色的属性,是数据内组合上下文需要的特性实现的。

    作者回复: 你的理解是对的,因为在 Java/C++这类语言中只有类这一个概念,所以,我们不得不用类表示所有的东西,之所以,要讲不同语言的做法,就是希望大家知道,自己写代码时,这个“类”扮演了什么角色。

    2020-06-30
    5
  • NIU
    所谓组合就是类的引用吧,面向对象编程时,如果不是继承关系,那大概率就是引用类来实现功能的组合吧

    作者回复: Java 的类引用可以表达很多概念,属性和组合都是通过同样的概念表示出来的。好处就是简单,坏处就不清楚。

    2020-06-29
    1
    4
  • 一步
    组合优于继承,可以使用继承的地方几乎都可以用组合替换的,那是不是说继承这个特性在现代编程语言中没有什么作用了(接口继承实力上就是多态)

    作者回复: 先看看现代程序设计语言的设计,比如,Go和Rust。

    2020-07-04
    2
  • Reason
    关于dci可参阅的代码案例太少了。了解起来找不到门。。

    作者回复: 是否能够快速学习一个新东西,就是程序员之间体现出差异的地方。

    2020-07-01
    2
  • 阳仔
    继承是面向对象的基本原则之一,但在编码实践中能用组合来实现尽量使用组合。
    DCI也是一种编码规范,它是对面向对象编程的一种补充,其实核心思想也是关注点分离

    作者回复: 很好的理解!

    2020-06-29
    2
  • Cc°°
    把一个 M*N 的问题,通过设计转变成了 M+N 的问题。
    这个应该是把2^N问题变为了N的问题吧?

    作者回复: 换了一个角度看,也是。

    2020-06-29
    2
  • 码农Kevin亮
    请问老师,组合我是理解的了。但文中提到的“小类大对象”中的大对象为什么强调是对象呢?为什么不是大类呢?还有说到这里时,又强调了面向对象而不是面向类,这又怎么理解其中在设计思想上的差异呢?

    作者回复: 这里的小类大对象是用 C++的方式描述的,每个类是小的,简言之代码都不多,最终形成的对象是个大的,因为它把所有的小类组合了起来。在运行时,用到的是对象,而设计中,你用到的是接口,是类层面的东西。

    2020-07-15
    1
  • jg4igianshu
    dci和mvc的模式是从看问题的角度来做系统组合。
    mvc是从数据传播角度来做组合,基于controller来组合model和view
    dci是从使用场景角度来做组合,基于context行为来操作data
    2020-07-05
    1
  • Julien

    MODULE(ProductFetcher) {
      ...
    }

    MODULE(ReportGenerator) {
      ...
    }

    class ReportService:
      INCLUDE(ProductFetcher),
      INCLUDE(ReportGenerator) {
      ...
    }
    这段代码,为什么不用组合呢?

    作者回复: 你说的字段的组合方式吧,可以用。但如果有更有语义的表示方式,选择更好的表示方式是一个更好的选择。

    2020-06-29
    1
    1
收起评论
10
返回
顶部