单一职责原则
定义是对于一个类,应该只有一个引起它变化的原因。
满足这个原则的优点是易于维护和高度的可复用性。
在职责扩散到无法控制的程度之前,进行代码重构。
需要足够简单的逻辑,才可以在代码级别上违反单一职责原则;类中方法足够少,才可以在方法级别上违反单一原则。
里氏代换原则(LSP)
lsp是反映父类和子类的关系。
- 对象的继承代表是一种“IS-A“的关系。也可以理解成继承者对被继承者的一种特殊化。
- 子类可以用父类的方法,但是不能选择性地继承父类。
- 继承表示一种类与类之间的相交关系。
LSP的定义是子类型必须能够替换他们的父类型。
LSP的精髓是子类型对于父类型的可替换性。
长方形和正方形:
1. 长方形有长和宽2个属性,而正方形其实只有边长一个属性。
2. 正方形有2个属性,长和宽相等。
开放-封闭原则(OC)
添加而不是修改 这是指对已有程序的扩展优先采用添加新的类或者模块的方式进行,而不是通过修改现有的类或者模块来进行。
这么做的好处是可以封装变化、降低耦合。
OC的定义是——程序的实体对象(模块、类、函数等)应该可以进行扩展,但不应该可以修改。
OC的2个特征:
- 对拓展是开放的
- 对修改是封闭的
当变化发生时,首先需要做的不是修改代码,而是尽可能地将变化抽象出来进行隔离,然后进行扩展。
动物会呼吸,猫不仅会呼吸,还会抓老鼠。
设计的模块决定那种变化封闭。比较好的方式是等到变化发生时立刻采取行动。
OC的核心思想是面向抽象编程,而不是面向具体编程,因为抽象相对稳定。
以银行的业务为例,比较实现OC和没OC的区别
依赖倒转原则(Ioc)
实现OC关键是实现抽象化,并且从抽象化得出具体的实例。若OC是面向对象设计的主要目标,那么依赖倒转就是面向对象设计的主要机制。
面向对象
起初是指程序设计中使用封装、继承、多态等设计的方法。
面对对象的分解根据抽象的关键问题域来分解系统。
Ioc的定义——程序的高层模块不应该依赖于底层模块,但两者都应该依赖于抽象;抽象不应该依赖于细节,而细节应该依赖于抽象。
面向对象应该针对接口编程,而不是针对实现编程。
Ioc的本质上通过抽象(接口、抽象类)使各个类或者模块的实现彼此独立,不相互影响,从而实现模块间的松散耦合。
需要遵循的几个规范:
- 每个类都尽量继承自接口或抽象类,或者抽象类和接口2者。接口和抽象类属于抽象。
- 变量的显示类型尽量是接口或者是抽象类。
- 变量的类型一定是接口或者是抽象类,过于绝对。
- 类要尽量避免从具体类派生。不超过2层的继承是可以接受的。看具体情况。
- 尽量不要覆盖基类的方法。类间依赖的是抽象,覆盖抽象方法,对于依赖的稳定性会产生影响。
Ioc的意义
Ioc就是要求客户端应当依赖于抽象耦合。
面向对象最重要的原则就是创建抽象化,同时从抽象化导出具体化,具体化给出不同的实现。继承的关系就是一种从抽象化到具体化的实现。
抽象层所包含的应该是应该是应用系统的商务逻辑和宏观的、对整体系统来说具体重要的战略的决定,也是必然性的体现。具体的层次含有是一些次要的与实现有关的算法以及逻辑,还有战术性的决定,这些都带有相当大的偶然性选择。
模版设计模式是依赖倒转原则的一个例子。
合成/聚合原则
合成和聚合都是关联关系的特殊种类,合成本质上是值的聚合,而我们所说的聚合是引用的聚合。在面向对象设计中,有两种基本的办法可以实现复用:第一种是通过合成/聚合;通过继承。
合成/聚合原则的定义——尽量不使用类继承,而尽量使用合成/聚合原则。
合成与聚合都是特殊的关联种类。聚合表示比较弱的拥有关系,具体表现是甲对象中可以包括乙对象,但乙对象不是甲对象的一部分;合成则是一种强的拥有关系,体现的是严格的整体与部分之间的关系,并且整体与部分有相同的生命周期。
鱼和鱼群是聚合关系,手臂与人体之间是部分和整体的关系。
要选择合成/聚合复用和继承的方法。只有当以下的条件全部都被满足时,应当使用继承关系:
1. 子类是父类的一个特殊种类,而不是父类的一个角色时,也就是区分“Has-A”和IS-A。只有IS-A关系才符合继承关系,Has-A关系应当用聚合来描述。
2. 永远不会出现需要将子类换成另外一个类的子类的情况时。如果不能肯定,就不应该用继承。
3. 子类具有扩展父类的责任,而不是重写父类的方法是。
4. 只有分类学角度上有意义时,才可以使用继承。
IS-A表示一个类是另外一个类的一种;Has-A表示一个类是另外一个类的角色。
当2个类满足里氏代换原则时,这2个类可以说Is-A关系。换句话说,若2个类的关系是Has-A,不能被设计为继承。
合成/聚合的优点和缺点
优点:
1. 新的对象存取子对象的唯一方法是通过子对象的接口。
2. 这种复用是黑箱的复用,因为子对象的内部细节上新对象看不到的。
3. 这种复用更好地支持封装的特性。
4. 这种复用实现的相互依赖性是比较小的。
5. 每个新的类都可以将焦点集中在一个任务之上。
6. 这种复用可以在运行时动态地进行,新的对象可以动态地引用与子对象类型相同的对象。
7. 作为复用手段几乎可以应用到任何环境中去。
缺点:
系统中有较多的对象需要管理。
迪米特法则
该法则也被称作为最少知识原则,就是说一个对象应当尽可能少地了解其他对象——不和陌生人说话。
解释:
一个软件的尸体应当尽可能少的与其他实体发生相互作用。
该法则的初衷是降低类之间的耦合。如果需要建立联系,也是希望通过其友元类来传达。
该法则的后果是系统中有大量的中介类。
该法则的定义——如果两个类之间不必直接通信,则这两个类不应该发生直接的相互作用。如果其中的一个类需要调用另外一个类的某个方法,可以通过第三方来转发这个调用。