当前位置: 首页 > article >正文

软件架构设计7大原则

设计原则

    • 1. 开闭原则(OCP - Open-Closed Principle)
    • 2. 单一职责原则(SRP - Single Responsibility Principle)
    • 3. 里氏替换原则(LSP - Liskov Substitution Principle)
    • 4. 依赖倒置原则(DIP - Dependency Inversion Principle)
    • 5. 接口隔离原则(ISP - Interface Segregation Principle)
    • 6. 迪米特法则(LoD - Law of Demeter)
    • 7. 组合优于继承(Composition Over Inheritance)
    • 总结

在Java软件开发中,有7大重要的设计原则,它们帮助开发者编写高内聚、低耦合可维护、可扩展的代码。这些原则也被称为SOLID原则 + 其他关键设计原则,它们是面向对象编程(OOP)和软件架构的核心。

  • 高内聚
  • 低耦合
  • 可维护
  • 可扩展

1. 开闭原则(OCP - Open-Closed Principle)

定义:

对扩展开放,对修改关闭。

含义:

  • 软件应该可以扩展新功能,而不应该修改已有代码。
  • 使用接口抽象类策略模式等方式来实现扩展。

示例:

// 定义抽象接口,避免修改原有代码
interface Shape {
    double calculateArea();
}

class Circle implements Shape {
    private double radius;
    public Circle(double radius) { this.radius = radius; }
    @Override
    public double calculateArea() { return Math.PI * radius * radius; }
}

class Rectangle implements Shape {
    private double width, height;
    public Rectangle(double width, double height) { this.width = width; this.height = height; }
    @Override
    public double calculateArea() { return width * height; }
}

✅ 好处: 新增 Triangle(三角形)时,只需实现 Shape 接口,不用修改原代码,符合开闭原则。


2. 单一职责原则(SRP - Single Responsibility Principle)

定义:

一个类应该只有一个引起它变化的原因。

含义:

  • 每个类 只负责 一个功能,避免过多职责耦合。
  • 增强代码的可读性可维护性

示例(违反单一职责):

class ReportManager {
    void generateReport() { /* 生成报表的逻辑 */ }
    void saveToDatabase() { /* 数据库存储逻辑 */ }
    void sendEmail() { /* 发送邮件逻辑 */ }
}

✅ 遵循单一职责原则(拆分成多个类):

class ReportGenerator {
    void generateReport() { /* 生成报表 */ }
}

class DatabaseSaver {
    void saveToDatabase() { /* 存储数据 */ }
}

class EmailSender {
    void sendEmail() { /* 发送邮件 */ }
}

好处: 各个类职责单一,避免代码臃肿、难维护


3. 里氏替换原则(LSP - Liskov Substitution Principle)

定义:

子类可以替换父类,并且不会影响父类的功能。

含义:

  • 子类应该能够扩展父类的功能,而不会改变父类的行为
  • 不能让子类破坏父类的逻辑,否则多态会失效。

示例(违反LSP):

class Bird {
    void fly() { System.out.println("Bird is flying"); }
}

class Penguin extends Bird { // 企鹅不会飞
    @Override
    void fly() { throw new UnsupportedOperationException("Penguin cannot fly!"); }
}

遵循LSP(重构):

interface Bird { }
interface FlyableBird extends Bird {
    void fly();
}

class Sparrow implements FlyableBird {
    @Override
    public void fly() { System.out.println("Sparrow is flying"); }
}

class Penguin implements Bird { /* 企鹅不会飞 */ }

好处: 避免子类破坏父类逻辑,保证多态的正确性。


4. 依赖倒置原则(DIP - Dependency Inversion Principle)

定义:

高层模块不应该依赖于低层模块,而应该依赖于抽象。

含义:

  • 上层代码 不依赖于 具体实现(类),而是依赖 接口或抽象类
  • 低层代码 也依赖 接口,而不是直接实现。

示例(违反DIP):

class MySQLDatabase {
    void connect() { System.out.println("Connecting to MySQL"); }
}

class Application {
    private MySQLDatabase database = new MySQLDatabase();
    void start() { database.connect(); }
}

遵循DIP(使用接口):

interface Database {
    void connect();
}

class MySQLDatabase implements Database {
    @Override
    public void connect() { System.out.println("Connecting to MySQL"); }
}

class Application {
    private Database database;
    public Application(Database database) { this.database = database; }
    void start() { database.connect(); }
}

好处:

  • 未来如果更换 PostgreSQLDatabase无需修改 Application 代码,增强灵活性。

5. 接口隔离原则(ISP - Interface Segregation Principle)

定义:

接口应该尽可能小,每个接口只定义特定功能,而不是一个大而全的接口。

含义:

  • 避免“胖接口”,不让类实现它们不需要的方法。
  • 通过多个小接口,提供更清晰的抽象。

示例(违反ISP):

interface Animal {
    void eat();
    void fly();
    void swim();
}

class Dog implements Animal {
    public void eat() { /* 正常实现 */ }
    public void fly() { throw new UnsupportedOperationException(); }  // 不需要
    public void swim() { /* 正常实现 */ }
}

遵循ISP(拆分接口):

interface Eater { void eat(); }
interface Flyer { void fly(); }
interface Swimmer { void swim(); }

class Dog implements Eater, Swimmer {
    public void eat() { /* 正常实现 */ }
    public void swim() { /* 正常实现 */ }
}

好处: 避免不必要的方法实现,提高代码灵活性


6. 迪米特法则(LoD - Law of Demeter)

定义:

一个类应该尽可能少地与其他类发生直接交互。

含义:

  • 最小知识原则(Least Knowledge Principle, LKP)一个对象应尽量减少对其他对象的依赖
  • 降低耦合度,减少不必要的依赖。

示例(违反LoD):

class Engine {
    void start() { System.out.println("Engine starting..."); }
}

class Car {
    Engine engine = new Engine();
    void start() { engine.start(); } // 直接访问Engine
}

遵循LoD(使用封装):

class Engine {
    void start() { System.out.println("Engine starting..."); }
}

class Car {
    private Engine engine = new Engine();
    void startCar() { engine.start(); } // 间接访问
}

好处: 避免暴露不必要的内部实现,降低代码耦合度。


7. 组合优于继承(Composition Over Inheritance)

定义:

优先使用“组合”来实现代码复用,而不是继承。

含义:

  • 继承耦合度高,父类变化会影响子类。
  • 使用组合(has-a关系)更灵活,可以在运行时动态替换组件。

示例(组合替代继承):

class Engine {
    void start() { System.out.println("Engine starting..."); }
}

class Car {
    private Engine engine;
    Car(Engine engine) { this.engine = engine; }
    void startCar() { engine.start(); }
}

好处: 增强灵活性,避免继承带来的复杂依赖。


总结

原则核心思想
OCP开闭原则:对扩展开放,对修改关闭
SRP单一职责:一个类只做一件事
LSP里氏替换:子类可以替换父类
DIP依赖倒置:依赖抽象而非具体实现
ISP接口隔离:接口要小而精,不要臃肿
LoD迪米特法则:减少耦合,少与其他类交互
组合优于继承使用组合代替继承,增强灵活性

熟练掌握这些原则,可以帮助你写出更灵活、可维护、可扩展的Java代码! 🚀


http://www.kler.cn/a/571198.html

相关文章:

  • ESP32之Flash操作
  • 11、HTTPS和HTTP有哪些区别【高频】
  • SSM开发(十四) Spring之IOC
  • 大模型——CogView4:生成中英双语高清图片的开源文生图模型综合介绍
  • DeepSeek vs Grok vs ChatGPT:大模型三强争霸,谁将引领AI未来?
  • Web⾃动化测试及常用函数
  • pnpm+monorepo实现前端公共函数、组件库
  • 芯麦 GC1272 芯片:电脑散热风扇领域的高效替代之选,对比 APX9172/茂达芯片优势解析
  • Linux基础 -- ARM 32位常用机器码(指令)整理
  • Deepseek的底层架构思维构成
  • 面试-----每日一题
  • android13打基础: 接收自定义广播并在接收到广播时触发设备震动
  • 3月4日C高级
  • 通往 AI 之路:Python 机器学习入门-线性代数
  • ffmpeg 添加字幕subtitles绝对路径
  • Servlet理论和tomcat(2)http
  • 制服小程序的“滑手”:禁用页面左右滑动全攻略
  • leetcode112-路径总和
  • 练习题:66
  • Python 矩阵对角线操作函数介绍