[架构师训练营] Week02 - 学习总结
编程的目的是用计算机来解决现实世界的问题。
编程的过程即:在计算机所能理解的模型(解空间)和现实世界(问题空间)之间,建立一种联系。
问题领域,包含与系统所要解决的问题相关的实物和概念的空间。
Booch对于对象的描述与:对象具有状态,行为和标识。
状态:表明每个对象可以由自己的数据。
行为:表明每个对象可以产生行为。
标识:表明每个对象都区别于其它的对象(唯一的地址)
面向对象编程的三要素(特征)
封装性(encapsulation)
隐藏实现细节(访问控制)
定义接口
继承性(inheritance)
IS-A关系
HAS-A关系(组合)
多态性(polymorphism)
后期绑定(虚函数)
向上转型(up casting)
面向对象的终极目标是:高内聚,低耦合。
面向对象的原则包括ocp(开闭原则,open/close原则), dip(依赖倒置原则,dependency inversion principle), lsp(替换原则,Liskov substitution principle), srp(单一职责原则,single responsibility principle), isp(interface segregation principle).
其中, ocp核心思想是:
扩展是开放的(open for extension)意味着模块的行为是可以扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。换句话说,我们可以改变模块的功能。
修改是关闭的(close for modification) 对模块行为进行扩展时,不必改动模块的源代码或者二进制代码。模块的二进制可执行文件,无论是可链接的库,DLL或者java的jar文件,都无需改变。
ocp例子
应用ocp原则后:
如果要扩展程序,使之能够绘制一种新的形状,我们只需要增加一个新的shape类的派生类。DrawAllShape函数并不需要改变,这样DrawAllShape就符合OCP。无需改动自身代码,就可以扩展它的行为。
开放的是扩展行为,关闭的是二进制可执行文件,dll, jar包,上面例子关注的是DrawAllShape。
dip核心思想:
高层模块不应该依赖于低层模块,二者都应该依赖于抽象。
抽象不应该依赖于细节。细节应该依赖于抽象。
DIP分层结构:
这里倒置的层次不仅仅是依赖关系的倒置,也是接口所有权的倒置。通常会认为工具库应该拥有自己的接口。但当应用DIP后,我们往往发现客户拥有抽象接口,而它们的服务者则从这些抽象接口派生。
DIP例子1:
应用DIP原则后:
lamp的确依赖于buttonserver, 但是buttonserver没有依赖于button, 任何知道如何去操纵buttonserver接口的对象都能够控制lamp.
DIP2例子:
应用DIP原则后:
对应的代码是:
lsp核心思想是:
子类型(subtype)必须能够替换掉它们的基类型(basetype).
替换性质:若对每个类型S的对象o1,都存在一个类型T的对象o2, 使得在所有针对T编写的程序P中,用o1替换o2后,程序P行为功能不变,则S是T的子类型。
假设有一个函数f, 它的参数为指向某个基类B的指针或者引用. 同样假设有B的某个派生类D, 如果把D的对象作为B类型传递给f, 会导致f出现错误的行为。那么D就违反了LSP. 显然, D对于f来说是脆弱的。
例子:
应用lsp原则后:
srp原则核心思想:
就一个类而言,应该仅有一个引起它变化的原因。
例子1:
应用srp原则后:
例子2:
应用srp原则后:
isp原则核心思想:
不应该强迫客户依赖于它们不用的方法。类的胖接口可以分解成多组方法。每一组方法都服务于一组不同的客户程序。这样,一些客户程序可以使用一组成员函数,而其他客户程序可以使用其他组的成员函数。
例子1:
优化后:
对应代码:
或者:
对应代码:
例子2:
优化后:
参考资料:
[Agile Software.Development:Principle. Patterns. and. Practices]((美)Robert.C.Martin).
评论