设计模式五大基本原则

设计模式中的五大基本原则,也称为SOLID原则,是面向对象设计的核心原则,它们帮助开发人员构建可扩展、可维护的系统。SOLID原则由罗伯特·C·马丁(Robert C. Martin)总结,这些原则的名称来自每个原则的首字母。它们分别是:

  1. 单一职责原则(Single Responsibility Principle,SRP)
  2. 开闭原则(Open/Closed Principle,OCP)
  3. 里氏替换原则(Liskov Substitution Principle,LSP)
  4. 接口隔离原则(Interface Segregation Principle,ISP)
  5. 依赖倒置原则(Dependency Inversion Principle,DIP)

1. 单一职责原则(SRP)

定义:一个类应该只有一个导致它变化的原因。

解释:每个类只应负责一项职责,或者说,一个类只应该有一个引起它变化的原因。职责越多,类的修改可能性越大,容易产生耦合问题。

例子

假设有一个 Employee 类负责员工信息存储和工资计算。如果未来业务需求变化,只需要修改工资计算的部分,但由于该类还包含其他职责,可能会无意中引入错误。

解决方案

Employee 类拆分为两个类,一个负责员工信息管理,一个负责工资计算。

kotlin 复制代码
class Employee {
    private String name;
    // 仅负责员工信息管理
}

class SalaryCalculator {
    // 负责工资计算
}

2. 开闭原则(OCP)

定义:软件实体应该对扩展开放,对修改关闭。

解释 :开闭原则的核心是通过扩展 而不是修改已有代码来应对需求的变化。换句话说,当我们需要新增功能时,应该通过新增代码(如新的类或模块),而不是修改已有代码。

例子

假设你有一个图形绘制系统,最初只能绘制圆形,现在需要扩展为绘制矩形。如果你直接修改原有代码,可能会引发新的问题。

解决方案

通过抽象类或接口来实现开闭原则,避免修改已有的绘图逻辑。

csharp 复制代码
interface Shape {
    void draw();
}

class Circle implements Shape {
    public void draw() {
        // 绘制圆形
    }
}

class Rectangle implements Shape {
    public void draw() {
        // 绘制矩形
    }
}

3. 里氏替换原则(LSP)

定义:派生类必须能够替换其基类,而不影响程序的正确性。

解释:子类可以替换父类并且保证程序行为不变。如果在使用基类的地方不能透明地替换为子类,那就违反了里氏替换原则。

例子

假设你有一个父类 Bird,它包含一个 fly 方法。然后你创建了一个子类 Penguin,但企鹅不能飞。如果你把企鹅放入需要飞行的地方,系统行为就会异常,违反了里氏替换原则。

解决方案

使用更具体的抽象,比如创建 FlyingBird 类,而不是让所有鸟类都继承 fly 方法。

scala 复制代码
class Bird {
    // 一般鸟类的属性和方法
}

class FlyingBird extends Bird {
    void fly() {
        // 具有飞行能力的鸟类
    }
}

class Penguin extends Bird {
    // 企鹅不具有飞行能力
}

4. 接口隔离原则(ISP)

定义:不应该强迫一个类实现它用不到的接口。

解释:与其让类实现一个庞大的接口,不如将接口拆分为多个更小、更具体的接口。这样,类只需要依赖它实际需要的接口方法。

例子

假设有一个 Worker 接口,包含 work()eat() 方法。如果一个机器人类需要实现 Worker 接口,它可能不需要 eat() 方法。

解决方案

将接口分解为更小的接口,让类按需实现它们。

csharp 复制代码
interface Workable {
    void work();
}

interface Eatable {
    void eat();
}

class Robot implements Workable {
    public void work() {
        // 机器人工作
    }
}

class Human implements Workable, Eatable {
    public void work() {
        // 人类工作
    }
    
    public void eat() {
        // 人类进食
    }
}

5. 依赖倒置原则(DIP)

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

解释:这个原则的重点是通过依赖抽象(接口或抽象类)来降低耦合度,而不是直接依赖具体实现。依赖倒置使系统更具灵活性和扩展性。

例子

假设你有一个 Button 类,它直接依赖于 Light 类来打开灯,这样会导致高层模块(Button)依赖于低层模块(Light)。

解决方案

通过依赖抽象,来降低类之间的耦合度。

csharp 复制代码
interface Switchable {
    void turnOn();
}

class Light implements Switchable {
    public void turnOn() {
        System.out.println("Light turned on");
    }
}

class Button {
    private Switchable device;

    public Button(Switchable device) {
        this.device = device;
    }

    public void press() {
        device.turnOn();
    }
}

通过依赖接口 SwitchableButton 类不再直接依赖 Light 类。这样,Button 可以用来控制任何实现了 Switchable 接口的设备。


总结

  1. 单一职责原则:一个类应只有一个引起变化的原因。
  2. 开闭原则:类应对扩展开放,对修改关闭。
  3. 里氏替换原则:子类可以替代父类而不影响系统的行为。
  4. 接口隔离原则:应提供小而专一的接口,避免依赖多余的方法。
  5. 依赖倒置原则:高层模块应依赖抽象,细节模块也应依赖抽象。
相关推荐
SunTecTec15 分钟前
Flink Docker Application Mode 命令解析 - 修改命令以启用 Web UI
大数据·前端·docker·flink
Java致死15 分钟前
工厂设计模式
java·设计模式·简单工厂模式·工厂方法模式·抽象工厂模式
codingandsleeping1 小时前
Express入门
javascript·后端·node.js
ss2731 小时前
基于Springboot + vue + 爬虫实现的高考志愿智能推荐系统
spring boot·后端·高考
拉不动的猪1 小时前
前端常见数组分析
前端·javascript·面试
全栈凯哥1 小时前
桥接模式(Bridge Pattern)详解
java·设计模式·桥接模式
小吕学编程2 小时前
ES练习册
java·前端·elasticsearch
Asthenia04122 小时前
Netty编解码器详解与实战
前端
袁煦丞2 小时前
每天省2小时!这个网盘神器让我告别云存储混乱(附内网穿透神操作)
前端·程序员·远程工作
专注API从业者2 小时前
《Go 语言高并发爬虫开发:淘宝商品 API 实时采集与 ETL 数据处理管道》
开发语言·后端·爬虫·golang