5.1 MM 请求修电脑
- 时间 : 3月12日19点 地点: 小菜大鸟住所的客厅 任务: 小菜, 大鸟, 娇娇
小菜和大鸟吃完晚饭后, 在一起聊天.
此是, 突然想起了声音.
“死了都要爱, 不淋漓精致不痛快, 感情多深只有这样, 才足够表白. 死了都要爱….”
….此处省略500字…
5.2 电话遥控修电脑
十分钟后.
“我在这儿等着你回来, 等着你回来, 看那桃花开. 我在这儿等着你回来, 等着你回来, 把那桃花采…..” 小菜的手机铃声再次响起.
“菜花痴, 你就不能找个好听的歌呀.” 大鸟气着说道.
…… 此处省略500字…
5.3 依赖倒转原则(Dependency Inversion Principle)
“小菜走桃花运了哦,” 大鸟有些羡慕到, “那铃声看来有些效果, 不过还是换掉吧, 俗!”
“嘿嘿, 你说也怪, 修电脑, 这在以前根本不可能的事儿, 怎么就可以通过电话就教会了, 而且是真的修到可以用了呢.”
“你有没有想过这里的最大原因?” 大鸟开始上课了.
“蓝屏通常是内存本身有问题或内存与主板不兼容,主板不容易换, 但内存更换起来很容易.”
“如果是别的部件坏了, 比如硬盘, 显卡, 光驱等, 是否也只需要更换就可以了?”
“是呀, 确实很方便, 只要懂一点点计算机知识, 就可以试着修电脑了.”
“想想这和我们编程有什么联系?”
“这个我记得最牢了, 就是活字印刷那个例子呗. 是可维护, 可扩展, 可复用和灵活性好. 哦, 我知道了, 可以吧 pc 电脑理解成是大的软件系统, 任何部件如 CPU, 内存, 硬盘, 显卡等都是可以理解为程序中封装的类或程序集, 由于 pc 以插拔的方式, 那么不管哪一个出问题, 都可以在不影响别的部件的前提下进行修改和替换.”
“pc 电脑叫做易插拔, 面向对象里把这种关系叫什么?”
“应该是叫高内聚, 松耦合吧.”
“对的, 非常好, 我们电脑里的CPU 全世界也就是那么几家生产的, 大家都在用, 但却不知道 intel, AMD 等公司是如何做出这个精密的小东西的. 去年国内不是还出现了汉芯造假的新闻吗! 这就说明 CPU 的内聚确实是强. 但他又独自成为了产品, 在千千万万的电脑主板上插上就可以使用, 这是什么原因?” 大鸟又问.
“因为 CPU 的对外都是针脚式或触点试等标准接口. 啊, 我明白了, 这就是接口的最大好处啊. CPU 只需要把接口定义好, 内部在复杂我也不让外界知道, 而主板只需要预留与CPU 针脚额插槽就可以了.”
“很好, 你已经在无意的谈话见提到了面向对象的几大设计原则, 比如我们之前讲过的单一职责原则, 就是刚才修电脑的事儿, 显然内存坏了, 不应该成为换 CPU 的理由, 他们各自的职责是明确的. 再比如开放—封闭原则, 内存不够只要插槽足够就可以添加, 硬盘不够可以用移动硬盘等, pc 的接口是有限的, 所以扩展有限, 软件系统设计的好, 却可以无限的扩展. 这两个原则我们之前都已经提过了. 这里需要重点讲讲一个新的原则, 叫依赖倒转原则, 也有翻译成依赖导致原则的.” 大鸟接着讲到, “依赖倒转原则, 原话解释是抽象不应该以来细节, 细节应该依赖于抽象, 这话绕口, 说白了, 就是要针对接口编程, 不要针对实现编程, 无论主板, CPU, 内存, 硬盘都是在针对接口设计的, 如果针对实现来设计, 内存就要对应到具体的某个品牌的主板, 那就会出现换内存需要把主板也换了的尴尬. 你想在小mm 面前表现也就不那么容易了. 所以说, pc 电脑硬件的发展, 和面向对象思想发展完全类似的. 这也说明世间万物都是遵循某种类似的规律, 谁先把屋了这些规律, 谁就最早成为强者.”
依赖倒转原则(Dependency Inversion Principle)
A. 高层模块不应该以来低层模块. 两个都应该依赖抽象.
B. 抽象不应该依赖细节. 细节应该依赖抽象. [ASD]
“为什么要叫倒转呢?” 小菜问道.
“这里面是需要好好解释一下, 面向过程开发是, 为了使得常用代码可以复用, 一般都会把这些常用代码写成许许多多函数的程序库, 这样我们在做新项目时, 去调用这些低层的函数就可以了. 比如我们我们做的项目大多要访问数据库, 所以我们就把访问数据库的代码写成了函数, 每次做新项目时就去调用这些函数. 这也就叫做高层模块依赖低层模块.”

“恩, 就是这样, 我以前都是这么做的, 这有什么问题?”
“问题也就出在这里, 我们要做新项目时, 发现业务逻辑的高层模块都是一样的, 但客户却希望使用不同的数据库做存储信息方式, 这时就出现麻烦了. 我们希望能再次利用这些高层模块, 但高层模块都是与低层的访问数据库绑定在一起的, 没办法复用这些高层模块, 这就非常糟糕了. 就像刚才说的, pc 里 如果 cpu, 内存, 硬盘都需要依赖具体的主板, 主板已坏, 所有的部件就都没用了, 这显然不合理. 反过来, 如果内存坏了, 也不应该造成其他部件不能用才对. 而如果不管高层模块还是低层模块, 他们都依赖于抽象, 具体一点就是接口或抽象类, 只要接口是稳定的, 那么任何一个的更改都不用担心其他收到影响, 这就使得无论高层模块还是低层模块都可以很容的被复用. 这才是最好的办法.”
“为什么依赖了抽象接口或抽象类, 就不怕更改了呢?” 小菜依旧疑惑, “不好意思, 我有些钻牛角尖了.”
“没有没有, 在这里弄不懂是很正常的, 原因是我少讲了一个设计原则, 使得你产生了困惑, 这个原则及时里氏代换原则.”
5.4 里氏代换原则
“里氏代换原则是 Barbara liskow 女士在1988 年发表的[ASD], 具体的数学定义比较复杂, 你可以查相关资料, 他的白话翻译就是一个软件实体如果使用的是一个父类的话, 那么一定是用于其子类, 而且他察觉不出父类对象和子类对象区别. 也就是说, 在软件里面, 把父类都替换成他的子类, 程序的行为没有发生变化, 简单地说, 子类型必须能替换掉他们的父类型[ASD].”
里氏代换原则(Liskov Substitution Principle): 子类型必须能够替换掉他们的父类型[ASD].
“这个好像是学继承时就要理解的概念, 子类继承了父类, 所以子类可以以父类的身份出现.”
“是的, 我们你个问题, 如果在面向对象设计师, 一个是鸟类, 一个是企鹅类, 如果鸟事可以飞的, 企鹅不会飞, 那么企鹅是鸟吗? 企鹅可以继承鸟这个类吗?”
“企鹅是一种特殊的鸟, 尽管不能飞, 但是他也是鸟呀, 当然可以继承”
“哈, 你上当了, 我说的是在面向对象设计时, 那就意味着什么么呢? 子类拥有父类所有非 private 的行为和属性. 鸟会飞, 额且不会飞. 尽管在生物学分支上, 企鹅一种鸟, 但在编程世界里, 企鹅不能以父类—鸟的身份出现, 因为前提说所有的鸟都能飞, 而企鹅飞不了, 所以, 企鹅不能继承鸟类.”

“哦, 我明白你的意思了, 我受了直觉的影响. 小时候上课时老师一再强调, 像鸵鸟, 企鹅等不会飞的动物也是鸟类.”
“也正是因为有了这个原则, 是的继承复用成为了可能, 只有当子类而已替换掉父类, 软件单位的功能不受影响是, 父类才能真正被复用, 子类也能够在父类的基础上增加新的的行为. 比方说, 猫是集成动物类, 动物的身份拥有吃, 和, 跑, 叫等行为, 可当某一天, 我们需要狗牛羊也拥有类似的行为, 由于他们都是继承于动物, 所以除了更改实例化的地方, 程序其他处不需要改变.”

|
|
“我的感觉, 由于有里氏代换原则, 才使得开放—封闭成为了可能.” 小蔡说.
“这样说也是可以的, 正是由于子类型的可替换性才使得使用父类类型的模块在无需修改的情况下就可以扩展. 不然还谈什么扩展开放, 修改关闭呢. 回过头来再看看依赖倒转原则, 高层模块不应该以来低层模块, 两个都应该依赖抽象, 对这就话你就会有更深入的理解了.”

“哦, 我明白了, 依赖倒转其实就是谁也不要依靠谁, 除了预定的接口, 大家都可以灵活自如. 还好, 他没有问我如何收音机, 收音机里面都是电阻, 三极管, 电路板等等东东, 全部焊接在一起, 我可不会修的.” 小菜庆幸道.
5.5 修收音机
“哈, 小菜你这比方打得好,” 大鸟开心的说, “收音机就是典型的耦合过度, 只要收音机出故障, 不管是没有声音, 不能调频, 还是有杂音, 反正都很难修, 不懂的人根本没法修, 因为任何问题都可能涉及其他部件, 各个部件相互依赖, 难以维护. 非常复杂的 pc 电脑可以修, 反而相对简单的收音机不能修, 这其实就说明很大的问题. 当然, 电脑的所维修也即是更换配件, CPU 或 内存要是坏了, 老百姓是没法修的. 现在在软件的世界里, 收音机式的强耦合开发还是太多了, 比如前段时间某银行出问题, 需要服务器停机大半天的排查修整, 这要损失多少钱. 如果完全面向对象设计, 或许问题的查找和修改就容易的多.依赖倒转其实可以说是面向对象设计的标识, 用哪种语言来编写程序不重要, 如果编写时考虑的都是如何针对抽象编程而不是针对细节编程, 及程序中所有的依赖关系都是终止与抽象类或者是接口, 那就是面型对象的设计, 反之那就是过程化了的设计[ASD].“
….. 一下省略的500字…..