一.单一职责原则:
单一职责原则(Single Responsibility Principle),简称SRP.简而言之就是一个类的设计尽量做到有且只有一个类的原因引起变化.
举个简单的例子,在平时我们可能会设置一个User类.
可能第一眼看这个接口没有什么不对劲,但是我们仔细想一想这个IUser接口真的只对应了一种职责吗?我们发现它对应了用户属性和用户行为两个职责,并且这两个职责的变化不互相影响.所以我们应该进行拆分.
单一职责原则能够降低类的复杂性,提高代码的可读性与可维护性,但是对于’单一职责’并没有严格的划分,有的时候单一职责的划分也不一定就是很好的.本来一个类硬要拆分成两个类显得过于麻烦,一个类职责进行混合也很常见,比如用筷子吃米饭,叉子吃泡面,但是我们也会有用筷子吃泡面,叉子吃米饭的时候,所以要适当的进行划分.建议接口一定要做到单一职责,类尽量做到只有一个原因引起变化.
二.里氏替换原则:
里氏替换原则(Liskov Substitution Principle),简称LSP.通俗的解释就是:只要父类出现的地方就能使用子类
.
就举车和人的例子
我们知道一个人有三台车,我们知道他会开车,但是我们不必知道他开的哪辆车,反正会跑就行.
Person person = new Person();
Car car = (Car)new BENZ();
person.setCar(car);
里氏替换原则增强了程序的健壮性,使程序更加的灵活,但是我们要注意在继承父类的方法后子类可以扩展父类的功能但不要修改父类的功能,这样会使得父类与子类的关系很难’调和’.
三.依赖倒置原则:
依赖倒置(Dependency Inversion Principle),简称DIP.简单的讲就是面向接口编程.
依赖倒置的主要表现主要有三点:
- 高层模块不应该依赖于底层模块,都应该依赖于其抽象.
- 接口或抽象类不依赖于实现类.
- 实现类依赖于接口或抽象类.
采用依赖倒置可以减少类间的耦合度,提高系统的稳定性,减少并行开发的风险.
还是举司机驾驶的例子:
在我们平常的生活中,会很理想当然的开奔驰车就用奔驰车,开宝马车就用宝马车.
但是问题来了,我不仅先开奔驰车又想开宝马车,怎么办呢?我们发现仅仅是增加一个不同的车,改动却要很大.
但是程序就是对世界的抽象,Driver完全可以不去管车型,知道它是车就行了.
显然,这样面向接口(抽象)的耦合度被大大降低,可扩展性也增加了.
现在我们也理解依赖倒置的’倒置’的含义了吧,与我们现实生活不同,当我们需要这个依赖时,不直接使用这个依赖(面向实现编程
),而是交由一个抽象的事物(面向接口编程
).
四.接口隔离原则:
接口隔离原则(interface segregation principle)要求接口尽量的细粒度
,这样系统才能更加的灵活.
还是车的例子:
我们定义了一个GoodCar的接口,认为跑的快.好看,跑的久就是好车,这当然是没问题的,可是往往某辆车在某个方面特别出色,比如说跑的超级超级快,但是看上去很丑,但这就不是一辆好车了吗?很明显这个GoodCar的接口就有问题了,我们应该继续进行拆分.
有人会把接口隔离原则与单一职责原则弄混,接口隔离原则与接口隔离原则的审视角度是不相同的,单一职责要求类和接口的职责单一,注重的是职责,这是业务逻辑上的划分,而接口隔离原则要求的是接口的方法尽量的少.但是我们在拆分接口的时候,也不要违反了单一职责原则.
五.迪米特法则:
迪米特法则(Law of Demeter):一个对象应该对其它对象最少的了解
,不要直接的和耦合的对象通信.
举例:
我们可以自己找女盆友,也可以通过朋友介绍,但是这样我们和女朋友也有了耦合,违反了迪米特法则.
我们只需要和朋友交流,不要自己找女盆友(cry~~~)
这样我们才是符合迪米特法则的.迪米特法则要求类不要公布太多的public方法和非静态的public变量,多内敛一点.
六.开闭原则
开闭原则(open closed principle):对拓展是开放的,对修改是关闭的.
举个书店的例子:
NovelBook是所有小说的实现类,我们现在有个需求,所有小说打0.7折,我们该怎么修改呢?
在NovelBook中重写getPrince()方法???很明显这样就不符合开闭原则了(对修改关闭),我们也会因此只关注了打折后的价格,而不知道原价格.
我们应该要扩展而不是修改.
开闭原则是很重要的,主要可以提高复用性和可维护性,但是也是无法百分百做到了,只是一个终极的目标.