1. 设计模式的目的
- 代码重用性:相同代码,无需多次编写
- 可读性:编程规范,易于阅读理解
- 可扩展性:易于扩展维护,新增功能
- 可靠性:新增功能对原有功能没有影响
- 高内聚、低耦合
2. 设计模式的原则
设计模式的原则,其实就是程序员在编程时,应当遵守的原则,也是各种设计模式的基础,即程序为什么这样设计
- 单一职责原则
- 接口隔离原则
- 依赖倒置原则
- 里式替换原则
- 开闭原则
- 迪米特法则
- 合成复用原则
2.1 单一职责原则
对类来说,一个类应该只负责一项职责。如果一个类负责多个职责,那么一个职责的变更可能导致其他职责错误,所以要将类的粒度进行分解
需求描述:交通工具的行驶
方案一:一个类负责多个职责
public class SingleResponsibility1 {
public static void main(String[] args) {
Vehicle vehicle = new Vehicle();
vehicle.run("摩托车");
vehicle.run("汽车");
vehicle.run("飞机");
}
}
// 交通工具类
class Vehicle {
public void run(String vehicle) {
System.out.println(vehicle + "在路上行驶");
}
}
分析:职责之间相互干扰
方案二:根据交通方式拆分成不同的类
public class SingleResponsibility2 {
public static void main(String[] args) {
RoadVehicle roadVehicle = new RoadVehicle();
roadVehicle.run("汽车");
roadVehicle.run("自行车");
AirVehicle airVehicle = new AirVehicle();
airVehicle.run("飞机");
SeaVehicle seaVehicle = new SeaVehicle();
seaVehicle.run("游艇");
}
}
// 不同交通工具类
class RoadVehicle {
public void run(String vehicle) {
System.out.println(vehicle + "在公路行驶");
}
}
class AirVehicle {
public void run(String vehicle) {
System.out.println(vehicle + "在天上飞");
}
}
class SeaVehicle {
public void run(String vehicle) {
System.out.println(vehicle + "在水中潜行");
}
}
分析:
- 遵守单一职责原则,但是改动较大,满足一定条件也可以只改动类方法,将低修改;
方案三:根据交通方式,在类中划分不同的方法
public class SingleResponsibility3 {
public static void main(String[] args) {
SuperVehicle superVehicle = new SuperVehicle();
superVehicle.runRoad("汽车");
superVehicle.runRoad("自行车");
superVehicle.runAir("直升机");
superVehicle.runSea("潜艇");
}
}
class SuperVehicle {
public void runRoad(String vehicle) {
System.out.println(vehicle + "在公路行驶");
}
public void runAir(String vehicle) {
System.out.println(vehicle + "在天上飞行");
}
public void runSea(String vehicle) {
System.out.println(vehicle + "在水中潜行");
}
}
原理分析:
- 这种方法没有对原来的类做较大修改,只是增加方法
- 虽然没有在类这个级别上遵守单一职责原则,但是在方法级别上,仍然遵守单一职责原则
原则注意事项和细节
- 降低类的复杂度,一个类只负责一项职责
- 提高类的可读性,可维护性
- 降低变更引起的风险
- 通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单才可以在代码级违反单一职责原则;只有类中方法数量足够少,可以在方法级别保持单一职责原则;
2.2 接口隔离原则
- 客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小接口上
- 如果接口中有子类用不到的方法,就把接口拆分成小接口,实现类只和他们需要的接口建立依赖关系
无接口隔离的情况
- 接口有1.2.3.4.5个方法,有B,D两个实现类,A,C依赖接口,
- 客户端A通过接口使用实现类B,需要使用方法1.2.3;客户端C通过接口使用实现类D,需要使用方法1.4.5
- 但是B实现接口要重写所有接口方法,D也是如此;
public class Segregation1 {
public static void main(String[] args) {
A a = new A();
a.depend1(new B());
a.depend2(new B());
a.depend3(new B());
C c = new C();
c.depend1(new D());
c.depend4(new D());
c.depend5(new D());
}
}
// 接口
interface Interface1 {
void operation1();
void operation2();
void operation3();
void operation4();
void operation5();
}
// 实现类
class B implements Interface1 {
public void operation1() {
System.out.println("B 实现了 operation1");
}
public void operation2() {
System.out.println("B 实现了 operation2");
}
public void operation3() {
System.out.println("B 实现了 operation3");
}
public void operation4() {
System.out.println("B 实现了 operation4");
}
public void operation5() {
System.out.println("B 实现了 operation5");
}
}
class D implements Interface1 {
public void operation1() {
System.out.println("D 实现了 operation1");
}
public void operation2() {
System.out.println("D 实现了 operation2");
}
public void operation3() {
System.