架构师训练营第二周总结
面向对象的编程
编程语言都在逐渐向面向对象转变,面向对象的编程语言也可能是目前的终极语言。
因为面向对象的方式是我们对社会问题的抽象,并将这种抽象用编程语言的形式表现出来,是跟社会问题本质最接近的方式。
面向对象的编程不是使用面向对象的编程语言编程、而是利用多态特性进行编程。
多态是面向对象的编程语言最重要的特性。
要用好多态最核心的一种能力就是抽象能力,对问题进行抽象,找到问题的本质,才能设计更好的设计。
就好像有一个需求需要一个人驾驶小汽车,那么仔细思考这个问题,进行抽象,是这个人要具备驾驶这样一种能力,他驾驶的并不固定是小汽车,也许未来需求增加还会让他驾驶公交车,甚至大货车,那么对人驾驶这个行为是进行了一种抽象。而小汽车、还是公交车、还是大火车实际上都是交通工具,那么再进行抽象,这个业务的本质是这个人需要驾驶一个交通工具。
小汽车、公交车、大货车都是交通工具的多态。
但是实际的业务开发并不像这个例子这么简单,那要进行抽象就需要我们深入的理解业务,从而仔细思考得到抽象的目的。
面向对象的设计目的
强内聚、低耦合,让系统
易扩展 易于增加新的功能
更强壮 不容易被粗心的程序员破坏
可移植 能够在多样的环境下运行
更简单 容易理解、容易维护
面向对象的设计原则
为了达到以上目的,有人总结出了多种设计指导原则
原则独立于编程语言,而是一种思想,一种方法论
设计模式
设计模式用于解决某一种问题的通用解决方案。
框架
框架是用来实现某一类应用的结构性程序,是对某一类架构方案可复用的设计和实现。
框架往往是框架来调用我们的代码,而不是我们调用框架。
工具是我们调用工具。
框架是架构师保证架构落地的手段。
工具是用来提升开发效率。
面向对象的设计的基本原则
软件设计的臭味
软件设计的最终目的,使软件达到“强内聚、低耦合”,从而让软件:易扩展、更强壮、可移植、更简单。
与之相反,一个不好的软件,会有以下臭味:
僵硬 不易改变
脆弱 只想改A,结果B被意外破坏
不可移植 不能适应环境的变化
导致误用的陷阱
晦涩
过度设计 复制粘贴代码
对过度设计的理解:
设计中包含不具任何直接好处的基础结构,或者包含当前没用用的组成部分,他就含有不必要的复杂性。
当开发人员预测需求的变化,并在软件中放置了处理那些潜在变化代码的时候,常常会出现这种问题。
对这句话的理解是,开发人员不要盲目的预测需求变化,应当更切合实际的结合当下需求进行设计,往往有时候你预测的变化可能根本不会来,而等到变化出现的时候再进行设计,并重构既有代码也是一种不错的选择。
开发以后完全不会变化的需求实际上设计也并不是有用的。
而针对那种真的经常变化的需求就需要有一个合理的设计,从而让这个代码拥抱变化。
优秀的程序员拥抱变化,因为他的设计就是为变化而生。
switch case if else语句是相当脆弱的,当一个代码中包含了过多的这种语法,就说明这段代码需要一个合理的设计了。
case后面的改变往往都是最频繁的,而else分支有第一个,以后就会有第二个、第三个。
OOD原则一:开闭原则(OCP)
开闭原则的思想是,对扩展是开放的、对修改是关闭的。
这个原则不是告诉我们对于既有代码不能修改,只能扩展。而是告诉我们,通过设计,让需求变更的时候可以通过扩展的方式满足,而不是通过修改满足需求的变化。
如何满足这样的需求?最关键的就是抽象!
OOD原则二:依赖倒置原则(DIP)
依赖倒置原则告诉我们,高层的模块不能依赖底层模块,而应该依赖抽象。
高层和底层一起都依赖抽象。
这样的好处是是抽象往往是最不容易改动的,如果抽象频繁改动,那可能说明你的抽象有问题。
抽象不易改变就决定了,无论高层改动,还是底层改动都不会对对方造成影响。这也就能保证了易扩展、更强壮的特性。
DIP倒置了什么?
模块和包的依赖关系
开发顺序和职责
依赖倒置最常应用的地方就是框架。
比如jdk的sql驱动框架,数据库驱动平台不依赖数据库厂商,而是依赖抽象,而厂商也依赖抽象,根据抽象实现驱动。
再比如mybatis框架,他抽象了xml的配置规则,抽象了mapper接口的定义规范,而具体实现的人根据这个规范来定义xml以及mapper接口,mybatis接口会在合适的时候调用我们的实现。
我们在理解依赖抽象这四个字的时候不能局限于依赖接口,这个抽象可以是接口,可以是一种规范,比如:
数据库驱动的抽象是一组接口,而mybaits的抽象是一种xml规范,而spring事物管理的抽象又是一种注解规范。
所以抽象是一种规范、接口、或者协议。
OOD原则三:Liskov替换原则(LSP)
里式替换原则的思想是子类型必须能够替换掉他们的基类型。
什么意思呢,比如这里有一个需求是人骑马,而马是一个抽象,具体的实现有白马、黑马。
那么当讲白马给人骑的时候,用黑马去替换一样是可以的,这就是里式替换。
里式替换是结合场景来分析的,如果我们在设计的时候发现一个场景中,继承的多个类之间不能替换,那我们这个设计之间可能就存在问题,或许应该考虑不用继承而使用其他方式来实现。
解决里式替换的办法是提取共性到基类、或者通过组合的方式来解决。
由is a转变为has a。
继承 VS 组合
继承和组合是OOP的两种扩展手段
继承比较容易,但继承破坏了封装,基类发生改变可能会层层影响其下的子类,继承是静态的,无法在运行时改变组合。
所以使用继承时应该优先考虑用组合是不是更合适。
OOD原则四:单一职责原则(SRP)
SPR又被称为内聚性原则,一个类,只能有一个引起他变化的原因。
一个职责就是一个变化的原因。
OOD原则五:接口分离原则(SRP)
不应该强迫客户程序依赖他们不需要的方法。
ISP和SRP时相关的,都和内聚性有关。
ISP指出应该如何设计一个接口,从客户的角度出发,强调不让客户看到他们不需要的方法。
评论