面向对象五大设计原则
以前一直认为程序中的类有使用到封装继承多态就是面向对象设计,其实不然
封装,继承,多态只是面向对象的三大特性,但是在设计程序的时候并不是说类的结构使用到了(或是体现出了)这三个特性就是面向对象,
其实真正的面向对象设计是要符合下面的五大原则,
面向对象的五大基本原则
单一职责原则(SRP)
开放封闭原则(OCP)
里氏替换原则(LSP)
依赖倒置原则(DIP)
接口隔离原则(ISP)
单一职责原则(SRP)
• 一个类应该有一个职责,仅有一个引起它变化的原因(最简单,最容易理解却最不容易做到的一个设计原则)
T类负责两个不同的职责:P1、P2. 当由于职责P1发生变化时有可能导致原本运行的P2功能发生故障.也就是说P1,P2被耦合在了一起,这种耦合会导致脆弱的设计并影响复用性。
开放封闭原则(OCP)
• 既开放又封闭,对扩展是开放的,对更改是封闭的!
• 扩展即扩展现行的模块,当我们软件的实际应用发生改变时,出现新的需求,就需要我们对模块进行扩展,使其能够满足新的需求!
更改封闭即是在我们对模块进行扩展时,勿需对源有程序代码和DLL进行修改或重新编译文件
这个原则对我们在设计类的时候很有帮助,坚持这个原则就必须尽量考虑接口封装,抽象机制和多态技术!
例如:设计一个加法运算器给客户,在设计之初 ,我们应该 将 一个运算的接口绑定给用户而后将具体的加法运算实现 运算的接口而不应该直接将加法抛给用户。如果用接口实现,在以后用户想进行减法运算时我们只需要再编写减法运算来实现运算的接口,而不必对原来的代码做出修改。从而实现对扩展开放,对修改关闭。
里氏替换原则(LSP)
• 子类可以替换父类并且出现在父类能够出现的任何地方
• 这个原则也是在贯彻GOF倡导的面向接口编程!
在这个原则中父类应尽可能使用接口或者抽象类来实现!
子类通过实现了父类接口,能够替父类的使用地方!
通过这个原则,我们客户端在使用父类接口的时候,通过子类实现!
意思就是说我们依赖父类接口,在客户端声明一个父类接口,通过其子类来实现
这个时候就要求子类必须能够替换父类所出现的任何地方,这样做的好处就是,在根据新要求扩展父类接口的新子类的时候而不影响当前客户端的使用!
鸵鸟非鸟: 如果以翅膀羽毛来区分鸟,那么显然鸵鸟是属于鸟的,是鸟它就应该有行为是飞也必然有飞行速度,而我们知道鸵鸟是不会飞的所以我们设置鸵鸟的飞行速度为0。
当客户想要测量鸟类飞跃黄河所需要的速度时 ,那么便会出现问题,由于鸵鸟的飞行速度为0,就会有除数出现0的情况。
面向对象的设计关注的是对象的行为,只有行为上一致的对象才能抽象成一个类,我们通常所说的继承是以 “ is a ” 为关系的实际上只关注属性的继承。而我们如果以飞这个行为来划分,鸵鸟显然不是鸟。
硬要以鸵鸟来继承鸟,实际上对于飞这个行为鸵鸟是无法覆盖父类的。
依赖倒置原则(DIP)
• 高层模块不应该依赖于低层模块,二者都应该依赖于抽象,抽象不应该依赖于细节,细节应该依赖于抽象。
例如 在ATM机取钱的时候,ATM机属于高层,我们手上的银行卡属于低层,ATM内只有普通银行卡共有的规格是一个抽象的接口,而不是存储各种银行卡的信息来进行判断。当某一种银行卡改变时我们不需要对ATM机做出改变,因为银行卡这个接口是不变的。从而增强了代码的复用性
ISP 接口隔离原则
• 这个原则的意思是:使用多个专门的接口比使用单个接口要好的多!
一个类对于一个类的依赖是建立在最小的接口上的,客户端不应该依赖于他不需要的接口。也就是说不应该强迫客户依赖他们不需要的方法。
例如: 对于公司的员工要工作的方法、吃饭的方法。我们用对象来实例化员工接口显然没有问题。但如果公司引进机器人来工作,若去实现员工的接口显然是有问题的,当然我们可以设置虚值来填补。但难免不会出错。
所以说员工这个接口是需要分离的。
而在实例化的时候我们可以实现多个接口,同样会达到目的。