面向对象的设计原则

面向对象程序设计有五大基本原则,也就是平常说的SOLID原则
S.O.L.I.D是面向对象设计和编程(OOD&OOP)中几个重要编码原则(Programming Priciple)的首字母缩写。

SRP The Single Responsibility Principle 单一职责原则
OCP The Open Closed Principle 开放封闭原则
LSP The Liskov Substitution Principle 里氏替换原则
DIP The Dependency Inversion Principle 依赖倒置原则
ISP The Interface Segregation Principle 接口分离原则

在这五大原则的基础上,还有两个常用原则
CRP Composite Reuse Principle 组合复用原则
LOD Law Of Demeter 迪米特原则

说一下这几个原则的概念

1.SRP The Single Responsibility Principle 单一职责原则又叫做单一功能原则
需要修改某个类的时候原因有且只有一个(THERE SHOULD NEVER BE MORE THAN ONE REASON FOR A CLASS TO CHANGE)
核心:解耦和增强内聚性(高内聚,低耦合),拆分到最小单位,解决复用和组合问题
个人理解:类的职责单一,引起类变化的原因单一。解释一下,这也是灵活的前提,如果我们把类拆分成最小的职能单位,那组合与复用就简单的多了,如果一个类做的事情太多,在组合的时候,必然会产生不必要的方法出现,这实际上是一种污染
优点和用途:
可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多
提高类的可读性,提高系统的可维护性
变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响

2.OCP The Open Closed Principle 开放封闭原则
软件实体应该是可扩展,而不可修改的
核心:对扩展开放,对修改关闭,即在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展,控制需求变动风险,缩小维护成本
个人理解:用户需求总是变化的,世界上没有一个软件是不变的,因此对软件设计人员来说,必须在保持原有系统正常运行的基础上,实现灵活的系统扩展
开放封闭原则是面向对象的第一原则,我们写完的代码,不能因为需求变化就修改。我们可以通过新增代码的方式来解决变化的需求。
当然,这是一种理想的状态,在现实中,我们要尽量的缩小这种修改
优点和用途:
我们遵循设计模式其他原则,以及使用23种设计模式的目的就是遵循开闭原则。也就是说,只要我们其他原则遵守的好了,设计出的软件自然是符合开闭原则的,这个开闭原则更像是前面其他遵守程度的“平均得分”,遵守的好,平均分自然就高,说明软件设计开闭原则遵守的好;如果原则遵守的不好,则说明开闭原则遵守的不好
开闭原则无非就是想表达这样一层意思:用抽象构建框架,用实现扩展细节。因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。而软件中易变的细节,我们用从抽象派生的实现类来进行扩展,当软件需要发生变化时,我们只需要根据需求重新派生一个实现类来扩展就可以了。当然前提是我们的抽象要合理,要对需求的变更有前瞻性和预见性才行

3.LSP The Liskov Substitution Principle 里氏替换原则
当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有is-A关系
核心:子类可以扩展父类的功能,但不能改变父类原有的功能,尽量使用精准的抽象类或者接口
个人理解:
子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法
子类中可以增加自己特有的方法
当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松
当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格
优点和用途:
继承作为面向对象三大特性之一,在给程序设计带来巨大便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加了对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能会产生故障

4.DIP The Dependency Inversion Principle 依赖倒置原则
高层模块不应该依赖于低层模块,二者都应该依赖于抽象
抽象不应该依赖于细节,细节应该依赖于抽象
核心:要依赖于抽象,不要依赖于具体的实现,面向抽象编程,解耦调用和被调用者
个人理解:就是面向接口编程,而不是面向过程,程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。
高层模块和低层模块的概念是相对的,当A class去new B class,A就是高阶模块,B就是低阶模块
高层模块依赖于接口或抽象类,低层模块实现接口或抽象类。依赖倒置原则其实就是谁也不依靠谁,除了约定的接口
问题描述:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。
解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率
优点和用途:
依赖倒置原则基于这样一个事实:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建起来的架构比以细节为基础搭建起来的架构要稳定的多。在java中,抽象指的是接口或者抽象类,细节就是具体的实现类,使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成

5.ISP The Interface Segregation Principle 接口分离原则
客户类不应被强迫依赖那些它们不需要的接口,一个类对另一个类的依赖应该建立在最小的接口上
核心:一个接口不需要提供太多的行为,一个接口应该只提供一种对外的功能,不应该把所有的操作都封装到一个接口当中,拆分,从接口开始
个人理解:接口隔离原则可以说是单一职责的必要手段,它的含义是尽量使用职能单一的接口,而不使用职能复杂、全面的接口。很好理解,接口是为了让子类实现的,如果子类想达到职能单一,那么接口也必须满足职能单一
相反,如果接口融合了多个不相关的方法,那它的子类就被迫要实现所有方法,尽管有些方法是根本用不到的。这就是接口污染。
问题描述:类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法。
解决方案:将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则
优点和用途:
很多人会觉的接口隔离原则跟之前的单一职责原则很相似,其实不然。其一,单一职责原则注重的是职责;而接口隔离原则注重对接口依赖的隔离。其二,单一职责原则主要是约束类,其次才是接口和方法,它针对的是程序中的实现和细节;而接口隔离原则主要约束接口接口,主要针对抽象,针对程序整体框架的构建

6.CRP Composite Reuse Principle 组合复用原则
如果只是达到代码复用的目的,尽量使用组合与聚合,而不是继承。这里需要解释一下,组合聚合只是引用其他的类的方法,而不会受引用的类的继承而改变血统
核心:尽量使用对象组合,而不是继承来达到复用的目的。该原则就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分:新的对象通过向这些对象的委派达到复用已有功能的目的,我只是用你的方法,我们不一定是同类
个人理解:相对于代码复用来讲,继承的耦合性大,比如一个父类后来添加实现一个接口或者去掉一个接口,那子类可能会遭到毁灭性的编译错误,但如果只是组合聚合,只是引用类的方法,就不会有这种巨大的风险,同时也实现了复用

7.LOD Law Of Demeter 迪米特原则
又叫作最少知道原则(Least Knowledge Principle 简写LKP),就是说一个对象应当对其他对象有尽可能少的了解,不和陌生人说话
核心:降低各个对象之间的耦合,提高系统的可维护性;在模块之间只通过接口来通信,而不理会模块的内部工作原理,可以使各个模块的耦合成都降到最低,促进软件的复用,类之间的直接联系尽量的少,两个类的访问,通过第三个中介类来实现
个人理解:一个软件实体应当尽可能少的与其它实体发生相互作用,你开车只需要了解如何开车就好,不需要知道汽车的内部构造,动力传递等过程,你只需要通过方向盘和油门开车就好
优点和用途:
迪米特法则的初衷是降低类之间的耦合,由于每个类都减少了不必要的依赖,因此的确可以降低耦合关系。但是凡事都有度,虽然可以避免与非直接的类通信,但是要通信,必然会通过一个“中介”来发生联系,过分的使用迪米特原则,会产生大量这样的中介和传递类,导致系统复杂度变大。所以在采用迪米特法则时要反复权衡,既做到结构清晰,又要高内聚低耦合

最后再回想总结一下:
单一职责原则告诉我们实现类要职责单一
里氏替换原则告诉我们不要破坏继承体系
依赖倒置原则告诉我们要面向接口编程
接口隔离原则告诉我们在设计接口的时候要精简单一
迪米特法则告诉我们要降低耦合
而开闭原则是总纲,他告诉我们要对扩展开放,对修改关闭

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值