1.1 MM请求电脑
MM电脑坏了,需要修电脑,是因为每次打开QQ,一玩游戏,机器就死了。出来蓝底白字的一堆莫名奇妙的英文。蓝屏死机了,估计内存有问题。
1.2 电话遥控修电脑
遥控修理电脑,打开内存条,两根内存条拔掉一个试试,最终有一个是好的,电脑修好了。
1.3 依赖倒转原则
蓝屏通常是内存本身有问题或内存与主板不兼容,主板不容易换,但是内存更换起来容易。
强内聚,松耦合。
依赖倒转原则是抽象不应该依赖细节,细节应该依赖于抽象,就是要针对接口编程,不要对实现编程。
依赖倒转原则
(1)高层模块不应该依赖低层模块。两个都应该依赖抽象。
(2)抽象不应该依赖细节。细节应该依赖抽象。
这里面是需要好好解释一下,面向过程的开发时,为了使得常用代码可以复用,一般都会把这些常用代码写成许许多多函数的程序库,这样我们在做新项目时,去调用这些低层的函数就可以了。比如我们做的项目大多要访问数据库,所以我们就把访问数据库的代码写成了函数,每次做新项目时就去调用这些函数。这也就叫作高层模块依赖低层模块。"
"嗯,是这样的,我以前都是这么做的。这有什么问题?"
"问题也就出在这里,我们要做新项目时,发现业务逻辑的高层模块都是一样的,但客户却希望使用不同的数据库或存储信息方式,这时就出现麻烦了。我们希望能再次利用这些高层模块,但高层模块都是与低层的访问数据库绑定在一起的,没办法复用这些高层模块,这就非常糟糕了。就像刚才说的,PC里如果CPU、内存、硬盘都需要依赖具体的主板,主板一坏,所有的部件就都没用了,这显然不合理。反过来,如果内存坏了,也不应该造成其他部件不能用才对。而如果不管高层模块还是低层模块,它们都依赖于抽象,具体一点就是接口或抽象类,只要接口是稳定的,那么任何一个更改都不用担心其他受到影响,这就使得无论高层模块还是低层模块都可以很容易地被复用。这才是最好的办法。"
"为什么依赖了抽象的接口或抽象类,就不怕更改呢?"不好意思,我有些钻牛角尖了。"
"没有,没有,在这里弄不懂是很正常的,原因是我少讲了一个设计原则,使得你产生了困惑,这个原则就是里氏代换原则。"
1.4 里氏替换原则
"里氏代换原则是Barbara Liskov女士在1988年发表的[ASD],具体的数学定义比较复杂,你可以查相关资料,它的白话翻译就是一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出父类对象和子类对象的区别。也就是说,在软件里面,把父类都替换成它的子类,程序的行为没有变化,简单地说,子类型必须能够替换掉它们的父类型[ASD]。"
里氏代换原则(LSP):子类型必须能够替换掉它们的父类型。[ASD]
"这好像是学继承时就要理解的概念,子类继承了父类,所以子类可以以父类的身份出现。"
"是的,我问你个问题,如果在面向对象设计时,一个是鸟类,一个是企鹅类,如果鸟是可以飞的,企鹅不会飞,那么企鹅是鸟吗?企鹅可以继承鸟这个类吗"
"企鹅是一种特殊的鸟,尽管不能飞,但它也是鸟呀,当然可以继承。"
"哈,你上当了,我说的是在面向对象设计时,那就意味着什么呢?子类拥有父类所有非private的行为和属性。鸟会飞,而企鹅不会飞。尽管在生物学分类上,企鹅是一种鸟,但在编程世界里,企鹅不能以父类——鸟的身份出现,因为前提说所有鸟都能飞,而企鹅飞不了,所以,企鹅不能继承鸟类。"
"哦,你的意思我明白了,我受了直觉的影响。小时候上课时老师一再强调,像鸵鸟、企鹅等不会飞的动物也是鸟类。所以上面的图,如果要让企鹅继承鸟,那么让鸟有下蛋的方法可以,但有飞的方法就不对了。"
"也正因为有了这个原则,使得继承复用成为可能,只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。比方说,猫是继承动物类的,以动物的身份拥有吃喝、移动(跑、飞、游等)等行为,可当某一天,我们需要狗、牛、羊也拥有类似的行为,由于它们都是继承于动物,所以除了更改实例化的地方,程序其他处不需要改变。"
"我的感觉,由于有里氏代换原则,才使得开放-封闭成为可能。"小菜说。
"这样说是可以的,正是由于子类型的可替换性才使得使用父类类型的模块在无须修改的情况下就可以扩展。不然还谈什么扩展开放,修改关闭呢?再回过头来看依赖倒转原则,高层模块不应该依赖低层模块,两个都应该依赖抽象,对这句话你就会有更深入的理解了。"
"哦,我明白了,依赖倒转其实就是谁也不要依靠谁,除了约定的接口,大家都可以灵活自如。还好,她没有问我如何修收音机,收音机里都是些电阻、三极管,电路板等东西,全都焊接在一起,我可不会修的。"小菜庆幸道。
1.5 修收音机
"收音机就是典型的耦合过度,只要收音机出故障,不管是没有声音、不能调频,还是有杂音,反正都很难修理,不懂的人根本没法修,因为任何问题都可能涉及其他部件,各个部件相互依赖,难以维护。非常复杂的电脑可以修,反而相对简单的收音机不能修,这其实就说明了很大的问题。当然,电脑的所谓修也就是更换配件,CPU或内存要是坏了,老百姓是没法修的。现在在软件世界里,收音机式的强耦合开发还是太多了,比如前段时间某银行出问题,需要服务器停机大半天的排查修整,这要损失多少钱。如果完全面向对象的设计,或许问题的查找和修改就容易得多。依赖倒转其实可以说是面向对象设计的标志,用哪种语言来编写程序不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者接口,那就是面向对象的设计,反之那就是过程化的设计了。