1.单一职责原则(Single Responsibility Principle)
单一职责原则的英文名称是Single Responsibility Principle,简称是SRP。单一职责原则的定义是:应该有且仅有一个原因引起类的变更。
单一职责原则好处如下:
- 类的复杂性降低,实现什么职责都有清晰明确的定义;
- 可读性提高,复杂性降低,那当然可读性提高了;
- 可维护性提高,可读性提高,那当然更容易维护了;
-变更引起的风险降低,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,这对系统的扩展性、维护性都有非常大的帮助。
2.里氏替换原则(Liskov Substitution Principle)
里氏替换原则的英文名称是Liskov Substitution Principle,简称是LSP。 里氏替换原则的定义有两种:
- 第一种定义:If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.(如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型。)
- 第二种定义:Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.(所有引用基类的地方必须能透明地使用其子类的对象。)
第二个定义是最清晰明确的,通俗点讲,只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类。但是,反过来就不行了,有子类出现的地方,父类未必就能适应。
3.依赖倒置原则(Dependence Inversion Principle)
依赖倒置原则的英文名称是Dependence Inversion Principle,简称是DIP。依赖倒置原则的原始定义是:
High level modules should not depend upon low level modules.Both should depend upon abstractions.(高层模块不应该依赖低层模块,两者都应该依赖其抽象);
Abstractions should not depend upon details.(抽象不应该依赖细节);
Details should depend upon abstractions.(细节应该依赖抽象)。
在JAVA中的描述为:模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的;接口或抽象类不依赖于实现类;实现类依赖接口或抽象类。
依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的
风险,提高代码的可读性和可维护性。
示例演示:
接口
package com.qqxhb.principal.dip;
/**
* 车接口
*
* @author Administrator
*
*/
public interface ICar {
/**
* 车运行
*/
public void run();
}
package com.qqxhb.principal.dip;
/**
* 司机接口 接口申明方式传递依赖
*
* @author Administrator
*
*/
public interface IDriver {
/**
* 驾驶方法
*
* @param car 具体驾驶的车
*/
public void drive(ICar car);
}
package com.qqxhb.principal.dip;
/**
* 司机接口 Setter方式传递依赖
*
* @author Administrator
*
*/
public interface ISetterDriver {
/**
* 驾驶方法
*
*/
public void drive();
/**
* @param car 具体驾驶的车
*/
public void setCar(ICar car);
}
package com.qqxhb.principal.dip;
/**
* 司机接口 构造器方式传递依赖
*
* @author Administrator
*
*/
public interface IConstractDriver {
public void drive();
}
汽车实现
package com.qqxhb.principal.dip.impl;
import com.qqxhb.principal.dip.ICar;
/**
* 奥迪汽车实现
*
* @author Administrator
*
*/
public class Audi implements ICar {
@Override
public void run() {
System.out.println("Audi Running....");
}
}
package com.qqxhb.principal.dip.impl;
import com.qqxhb.principal.dip.ICar;
/**
* 奔驰汽车实现
*
* @author Administrator
*
*/
public class BENZ implements ICar {
@Override
public void run() {
System.out.println("BENZ Running....");
}
}
package com.qqxhb.principal.dip.impl;
import com.qqxhb.principal.dip.ICar;
/**
* 宝马汽车实现
*
* @author Administrator
*
*/
public class BMW implements ICar {
@Override
public void run() {
System.out.println("BMW Running....");
}
}
司机实现
package com.qqxhb.principal.dip.impl;
import com.qqxhb.principal.dip.ICar;
import com.qqxhb.principal.dip.IConstractDriver;
/**
* 司机实现
*
* @author Administrator
*
*/
public class ConstractDriver implements IConstractDriver {
private ICar car;
public ConstractDriver(ICar car) {
this.car = car;
}
@Override
public void drive() {
car.run();
}
}
package com.qqxhb.principal.dip.impl;
import com.qqxhb.principal.dip.ICar;
import com.qqxhb.principal.dip.IDriver;
/**
* 司机实现
*
* @author Administrator
*
*/
public class Driver implements IDriver {
@Override
public void drive(ICar car) {
car.run();
}
}
package com.qqxhb.principal.dip.impl;
import com.qqxhb.principal.dip.ICar;
import com.qqxhb.principal.dip.ISetterDriver;
/**
* 司机实现
*
* @author Administrator
*
*/
public class SetterDriver implements ISetterDriver {
private ICar car;
@Override
public void drive() {
this.car.run();
}
@Override
public void setCar(ICar car) {
this.car = car;
}
}
客户端调用
package com.qqxhb.principal;
import com.qqxhb.principal.dip.ICar;
import com.qqxhb.principal.dip.IConstractDriver;
import com.qqxhb.principal.dip.IDriver;
import com.qqxhb.principal.dip.ISetterDriver;
import com.qqxhb.principal.dip.impl.Audi;
import com.qqxhb.principal.dip.impl.BENZ;
import com.qqxhb.principal.dip.impl.BMW;
import com.qqxhb.principal.dip.impl.ConstractDriver;
import com.qqxhb.principal.dip.impl.Driver;
import com.qqxhb.principal.dip.impl.SetterDriver;
public class Client {
public static void main(String[] args) {
/*
* 接口声明依赖对象
*/
IDriver driver = new Driver();
ICar car = new BENZ();
driver.drive(car);
/*
* Setter方法传递依赖对象
*/
ISetterDriver setterDriver = new SetterDriver();
car =new BMW();
setterDriver.setCar(car);
setterDriver.drive();
/*
* 构造函数传递依赖对象
*/
car =new Audi();
IConstractDriver constractDriver = new ConstractDriver(car);
constractDriver.drive();
}
}
我们在实际项目中尽量遵循以下几个规则:
- 每个类尽量都有接口或抽象类,或者抽象类和接口两者都具备
- 变量的表面类型尽量是接口或者是抽象类(必须util类就不需要)
- 任何类都不应该从具体类派生
- 尽量不要覆写基类的方法
如果基类是一个抽象类,而且这个方法已经实现了,子类尽量不要覆写。类间依赖的是抽象,覆写了抽象方法,对依赖的稳定性会产生一定的影响。 - 结合里氏替换原则使用
接口负责定义public属性和方法,并且声明与其他对象的依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑,同时在适当的时候对父类进行细化。
4.接口隔离原则(Interface Segregation Principle ISP)
接口分为两种:
- 实例接口(Object Interface),在Java中声明一个类,然后用new关键字创建实例。如 Car audi = new Car();Car类就是audi的接口。
- 类接口(Class Interface),Java中经常使用的interface关键字定义的接口。
隔离也有两种定义: - Clients should not be forced to depend upon interfaces that they don’t use.(客户端不应该依赖它不需要的接口。)
- The dependency of one class to another one should depend on the smallest possible interface.(类间的依赖关系应该建立在最小的接口上。)
简单来说就是 建立单一接口,不要建立臃肿庞大的接口即接口尽量细化,同时接口中的方法尽量少。他与单一职责原则的不同之在于:接口隔离原则与单一职责的审视角度是不相同的,单一职责要求的是类和接口职责单一,注重的是职责,这是业务逻辑上的划分,而接口隔离原则要求接口的方法尽量少。
5.迪米特法则(Law of Demeter,LoD)
迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge
Principle,LKP):一个对象应该对其他对象有最少的了解,也就是说一个类应该对自己需要耦合或调用的类知道得最少,至于被依赖对象的内部多么复杂调用者都不需要知道。
迪米特法则的核心观念就是类间解耦,弱耦合,只有弱耦合了以后,类的复用率才可以提高。其要求的结果就是产生了大量的中转或跳转类,导致系统的复杂性提高,同时也为维护带来了难度。迪米特法则要求类间解耦,但解耦是有限度的,在实际的项目中,需要适度地考虑这个原则。
6.开闭原则(Open Closed Principle,OCP)
开闭原则的定义如下:Software entities like classes,modules and functions should be open for extension but closed for modifications.(一个软件实体如类、模块和函数应该对扩展开放,对修改关闭)。
其含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。
软件实体包括以下几个部分:项目或软件产品中按照一定的逻辑规则划分的模块;抽象和类;方法。
开闭原则告诉我们应尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来完成变化,它是为软件实体的未来事件而制定的对现行开发设计进行约束的一个原则。