Skip to content

设计模式:六大原则

ZhangPan edited this page Jul 16, 2025 · 4 revisions

1.单一职责原则(SRP)

定义​: 一个类应该只有一个引起它变化的原因,即一个类应该只负责一项职责

核心思想​:

每个类只实现单一的职责,否则就应该把类拆开 不仅适用于类的设计,还适用于接口和方法的设计

优点​:

  • 降低类的复杂度,使代码更清晰易懂
  • 提高代码的可维护性和可扩展性
  • 更有利于代码高内聚,低耦合
  • 可读性更高,每个类职责清晰
  • 出现bug或业务变更时,可快速锁定修改范围
// 违反SRP的示例
class Employee {
    public void workForProduceManager() { /* 整理需求文档 */ }
    public void workForDeveloper() { /* 写代码 */ }
}

// 符合SRP的改进
interface Employee { void work(); }

class ProduceManager implements Employee {
    @Override public void work() { /* 整理需求文档 */ }
}

class Developer implements Employee {
    @Override public void work() { /* 写代码 */ }
}

2. 开闭原则(OCP)

定义​: 软件实体(类、模块、函数等)应对扩展开放,对修改关闭 。

​核心思想​:

  • 当程序需要扩展时,不去修改原有的代码,而是扩展原有代码
  • 用抽象构建框架,用实现扩展细节

优点​:

  • 减少代码修改风险,提高代码稳定性和可维护性
  • 能够扩展已有功能,满足新需求
  • 不需要修改已有代码,保证原有功能稳定性

实现方式​:

  • 充分利用抽象类和接口、多态等特性
  • 将可变部分封装起来
  • 常见于依赖注入、策略模式等设计模式中
// 违反OCP的示例
class Shape {
    int type; // 1=矩形, 2=圆形
}

class GraphicEditor {
    public void drawShape(Shape s) {
        if(s.type == 1) drawRectangle(s);
        else if(s.type == 2) drawCircle(s);
        // 添加新形状需要修改此处
    }
}

// 符合OCP的改进
abstract class Shape { abstract void draw(); }

class Rectangle extends Shape {
    @Override void draw() { /* 画矩形 */ }
}

class Circle extends Shape {
    @Override void draw() { /* 画圆形 */ }
}

class GraphicEditor {
    public void drawShape(Shape s) { s.draw(); } // 无需修改
}

3. 里氏替换原则(LSP)

​定义​: 所有引用基类的地方必须能透明地使用其子类的对象。

​核心思想​:

  • 子类必须能够替换其基类而不会引起程序行为的改变
  • 应优先使用对象组合而不是类继承
  • 由Barbara Liskov在1987年提出

​原则要求​

  • 子类必须实现父类抽象方法,但不得重写(覆盖)父类的非抽象方法
  • 子类中可以增加自己特有的方法
  • 子类方法的前置条件(入参)要比父类更宽松
  • 子类方法的后置条件(返回值)要比父类更严格
// 违反LSP的示例
class Bird { void fly() { /* 鸟会飞 */ } }
class Ostrich extends Bird { // 鸵鸟不会飞
    @Override void fly() { throw new UnsupportedOperationException(); }
}

// 符合LSP的改进
abstract class Bird { abstract void move(); }
class Sparrow extends Bird { 
    @Override void move() { /* 飞 */ } 
}
class Ostrich extends Bird {
    @Override void move() { /* 跑 */ } 
}

设计意义​:

  • 继承复用的基石,只有当衍生类可以替换基类,基类才能真正被复用
  • 对"开-闭"原则的补充,是实现抽象化的具体步骤的规范

4. 接口隔离原则(ISP)

定义​: 客户端不应该依赖它不需要的接口;类间的依赖关系应该建立在最小的接口上。

​核心思想​:

  • 每个接口中不存在子类用不到却必须实现的方法
  • 将臃肿的接口拆分为多个功能单一的独立接口

​优点​:

  • 降低系统耦合度
  • 提升系统灵活性:新增功能只需扩展特定接口
  • 增强代码可维护性:接口变更影响范围限定在相关客户类内部

​与SRP的区别​:

  • SRP强调类职责单一,ISP侧重接口依赖精简
  • SRP作用于方法/类级别,ISP聚焦接口架构设计
  • SRP提升内聚性,ISP降低耦合度
// 违反ISP的示例
interface Animal {
    void eat();
    void swim(); // 对不会游泳的动物是负担
}

class Dog implements Animal {
    @Override public void eat() { /* 吃 */ }
    @Override public void swim() { throw new UnsupportedOperationException(); }
}

// 符合ISP的改进
interface Eatable { void eat(); }
interface Swimmable { void swim(); }

class Dog implements Eatable { /* 只需实现eat */ }
class Fish implements Eatable, Swimmable { /* 实现两者 */ }

实现模式​:

  • 委托模式:通过创建适配器类实现接口转发
  • 多重继承:允许目标类同时继承多个专用接口

5. 依赖倒置原则(DIP)

​定义​: 高层模块不应该依赖低层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。

核心思想​:

  • 面向接口编程,依赖于抽象而不依赖于具体
  • 相对于细节的多变性,抽象的东西要稳定得多

​实现技术​:

  • 依赖注入(DI):通过构造器、setter或接口注入依赖
  • 控制反转(IoC):将控制权交给容器或框架

​优点​:

  • 降低类间耦合度,提高系统稳定性
  • 提高代码可读性、可维护性和扩展性
  • 促进高内聚低耦合设计
// 违反DIP的示例
class Computer {
    private Keyboard keyboard;
    private Mouse mouse;
    // 直接依赖具体实现
}

// 符合DIP的改进
interface InputDevice { void input(); }

class Keyboard implements InputDevice { /* 实现 */ }
class Mouse implements InputDevice { /* 实现 */ }

class Computer {
    private List<InputDevice> devices; // 依赖抽象
}

高级应用​:

  • 框架设计与扩展
  • 分层架构与解耦
  • 插件架构与动态扩展
  • 策略模式的运用

6. 迪米特法则(LoD)/最少知道原则

定义​: 一个对象应该对其他对象有最少的了解,只与直接的朋友通信。

核心思想​:

  • 类之间只要有耦合关系,就是朋友关系
  • 一个类对自己依赖的类知道的越少越好
  • 尽量减少一个对象对其他对象的直接依赖,尤其是对链式调用的依赖

​优点​:

  • 降低类间耦合
  • 提高模块的相对独立性
  • 当依赖的类发生变化时,才能最小的影响该类
// 违反LoD的示例
class Customer {
    private Wallet wallet;
    public float getWalletMoney() {
        return wallet.getMoney(); // 直接访问钱包内部
    }
}

// 符合LoD的改进
class Customer {
    private Wallet wallet;
    public float pay(float payment) {
        return wallet.subtractMoney(payment); // 通过钱包提供的接口操作
    }
}

实践建议​:

  • 在类结构设计上,尽量降低成员的访问权限
  • 优先考虑将类设置成不变类
  • 尽量降低一个类对另一个类的依赖

总结

设计模式六大原则首字母联合起来就是SOLID(两个L算做一个),代表建立稳定、灵活、健壮的设计。这些原则相互关联、相辅相成:

  1. 单一职责原则是实现高内聚低耦合的基石
  2. 开闭原则是面向对象设计的终极目标
  3. 里氏替换原则是实现继承复用的前提
  4. 接口隔离原则是降低系统耦合度的有效手段
  5. 依赖倒置原则是面向接口编程的核心
  6. 迪米特法则是减少类间依赖的实践指南

在实际开发中,这些原则需要灵活运用而非机械套用。理解原则背后的思想比死守规则更重要,有时需要在不同原则间做出权衡。优秀的设计往往是这些原则综合应用的结果,它们共同指导我们构建更健壮、更易维护的软件系统

更多参考:http://www.uml.org.cn/sjms/201211023.asp#1

公众号:玩转安卓Dev

Java基础

面向对象与Java基础知识

Java集合框架

JVM

多线程与并发

设计模式

Kotlin

Android

项目相关问题

Android基础知识

Android消息机制

Android Binder

View事件分发机制

Android屏幕刷新机制

View的绘制流程

Activity启动

Framework

性能优化

Jetpack&系统View

第三方框架实现原理

计算机网络

算法

Clone this wiki locally