这个学习是很久以前在网上学的,由于没有找到上次学的博客,就把这个笔记放上面吧,供日后开发使用
其中为用的最多的是单一职责,依赖倒转这两个原则,里面的迪米特法则很有趣哦.
里面提到的程序示例可以在我的主页里面下载.
1,目的
为了更好的代码重用性,可读性,可靠性,可维护性。
2,六大设计模式
1.单一职责原则 针对 类
2.里氏替换原则 针对 继承
3.依赖倒转原则 面向 接口
4.接口隔离原则
5.迪米特法则
6.开闭原则
3,单一职责原则
针对类 一个类只负责一项职责。
如果类T负责两个不同的职责:p1,p2。当p1需求变更而改变T时,可能造成职责p2发生故障,所以要将类T的粒度分解为T1,T2
Animal.cpp 描述动物呼吸这个场景
04Animal.cpp中的修改方式没有改动原来的方法,而是在类中新加了一个方法,这样虽然违背了单一职责原则,但在方法级别上却是符合单一职责原则。那么在实际编程中,采用哪一种呢?我的原则是,只有逻辑足够简单,才可以在代码级违反单一职责原则;只有类中方法数量足够少,才可以在方法级别违反单一职责原则。
遵循单一职责的优点:
1)降低类的复杂度,一个类只负责一项职责。
2)提高类的可读性,可维护性。
3)降低变更引起的风险。
4,里氏替换原则
如果每个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有对象o1都代换为o2时,程序P的执行行为没有发生变化,那么类型T2就是类型T1的子类。
换句话说,所有引用基类的地方必须能透明地使用其子类的对象。
所以,在继承时,尽量不重写或重载基类的方法。
继承包含这样一层含义:父类中凡是已经实现好的方法(相对抽象方法而言),实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。而里氏替换原则就是表达了这一层含义。
继承作为面向对象三大特性之一,在给程序设计带来巨大遍历的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能产生故障。
05Sub.cpp来浮现继承的这种风险。
重写了父类的方法,造成原有功能出现错误。在实际编程中,我们常常会通过重写父类的方法完成新的功能,这样写起来虽然简单,但整个继承体系的复用性会比较差。特别是运行多态比较频繁的时候,如果非要重写父类的方法,通用的做法是:原来的父类和子类都继承一个更通俗的基类,原有的继承关系去掉,采用依赖,聚合,组合等关系代替。
5,依赖倒转原则
高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。
类A直接依赖类B,如果要将类A改为依赖类C,则必须通过修改类A的代码来达成。此时,类A一般是高层模块,负责复杂的业务逻辑,类B和类C是低层模块,负责基本的原子操作;修改A会给程序带来风险。
将类A修改未依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或类C发生联系,则会大大降低修改类A的几率。
依赖倒置原则基于这样一个事实:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在c++中,抽象指的是抽象类,细节就是具体的实现类,使用抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
依赖倒置的中心思想是面向接口编程。
07Interdace.cpp
08Interdace.cpp 里面采用了抽象类的方式
依赖关系的传递有三种方式:接口传递,构造方法,和setter方法传递
09Interdace.cpp阐述了这三种方法。
实际编程中,一般需要做到:
1,低层模块尽量都要有抽象类。
2,变量的声明类型尽量是抽象类。
3,使用继承时遵循里氏替换原则。
6,接口隔离原则
客户端不应该依赖于他不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
类A通过I接口依赖于类B,类C通过接口I依赖类D,如果接口I对类A和类C来说,不是最小接口,则类B和类D必须去实现他们不需要的方法。
将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则。
10Interface.cpp
接口隔离原则和之前的单一职责原则很相似,其实不然。一,单一职责注重职责,而接口隔离原则注重对接口依赖的隔离;二,单一职责是约束类,其次是方法,针对的是程序中的实现和细节;而接口隔离原则约束的是接口,针对的是抽象,程序整体框架的构建。
7,迪米特法则
一个对象应该对其他对象保持最少的了解。
类与类关系越密切,耦合度越大。
迪米特法则又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的public 方法,不对外泄露任何信息。
迪米特法则还有个更简单的定义:只与直接的朋友通信。
什么是直接的朋友:每个对象都会与其他对象由耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖,关联,组合,聚合等。其中,我们称出现成员变量,方法参数,方法返回值中的类为直接的朋友,而出现在局部变量中的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量的形式出现在类的内部。
举例说明如下,有一个集团公司,下属单位有分公司和直属部门,现要求打印出所有下属单位的员工ID。
11Emplotee.cpp
12Emplotee.cpp
迪米特法则的初衷是降低类之间的耦合,由于每个类都减少了不必要的依赖,因此的确可以降低耦合关系。
8, 开闭原则
一个软件实体如类,模块和函数应该对扩展开放,对修改关闭。用抽象构建框架,用实现扩展细节。
当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
当我们遵循前面介绍的5大原则,以及使用23中设计模式的目的就是遵循开闭原则。