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

Java设计模式是什么?核心设计原则有哪些?

文章目录

  • 什么是设计模式?
  • 为什么使用设计模式?
  • 设计模式的核心设计原则是什么?
    • 1. 开闭原则(Open-Closed Principle, OCP)
    • 2. 里氏替换原则(Liskov Substitution Principle, LSP)
    • 3. 依赖倒置原则(Dependency Inversion Principle, DIP)
    • 4. 单一职责原则(Single Responsibility Principle, SRP)
    • 5. 接口隔离原则(Interface Segregation Principle, ISP)
    • 6. 迪米特法则(Law of Demeter, LoD)
    • 7. 合成/聚合复用原则(Composite Reuse Principle, CRP)
    • 七大原则的核心价值总结
  • 常见的设计模式有哪些?

作为一个Java开发程序员,设计模式就像是习武之人的内功心法,直接少走20年弯路,其重要性显而易见。通过掌握7大设计原则、23种设计模式,可以编写出 高内聚、低耦合、易扩展、易维护 的高质量代码,应对复杂软件系统的设计。

什么是设计模式?

  • 设计模式,是一套被反复使用、多数人知晓的、经过分类编目的代码设计经验的总结。

  • 他描述了在软件设计过程中的一些不断重复出现的问题,以及该问题的解决方案。也就是说,他是解决特定问题的一系列套路,是前辈们的代码设计经验的总结,具有一定的普遍性,可以反复使用。


为什么使用设计模式?

  • 设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。
  • 正确使用设计模式具有以下优点:
    • 可以提高程序员的思维能力、编程能力和设计能来。
    • 使程序设计更加标准化、代码编程更加工程化,使软件开发效率大大提高,从而缩短软件开发的周期。
    • 使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。

设计模式的核心设计原则是什么?

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

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

    • 扩展开放:通过新增代码(如新类、新模块)来实现功能扩展。
    • 修改关闭:不修改已有代码即可满足新需求。
  • 核心思想

    • 抽象约束:通过接口或抽象类构建稳定的抽象层,隔离变化点。
    • 封装变化:将可变因素封装在具体实现类中,需求变更时只需新增或调整实现类。
  • 示例

    // 抽象接口(稳定层)
    interface Shape {void draw();
    }// 具体实现类(可扩展)
    class Circle implements Shape {public void draw() {System.out.println("Drawing Circle");}
    }class Rectangle implements Shape {public void draw() {System.out.println("Drawing Rectangle");}
    }// 客户端代码(无需修改)
    public class Main {public static void main(String[] args) {Shape shape = new Circle();shape.draw(); // 输出:Drawing Circle}
    }
    
  • 好处

    • 降低维护成本:无需修改已有代码,减少引入新错误的风险。
    • 提高扩展性:通过新增实现类即可支持新功能(如新增 Triangle 类)。
    • 增强稳定性:抽象层保持不变,系统架构更稳定。

2. 里氏替换原则(Liskov Substitution Principle, LSP)

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

    • 子类替换父类:子类对象应能完全替代父类对象,且程序行为和结果不受影响。
  • 核心思想

    • 行为一致性:子类应继承父类的契约,不破坏父类定义的规范。
    • 避免副作用:子类不应强制改变父类的行为预期。
  • 示例

    // 父类
    abstract class Vehicle {abstract void start();
    }// 子类(符合 LSP)
    class Car extends Vehicle {public void start() {System.out.println("Car starts");}
    }// 错误示例(违反 LSP)
    class BrokenCar extends Vehicle {public void start() {System.out.println("Car explodes"); // 破坏父类行为预期}
    }
    
  • 好处

    • 代码复用性:子类可安全复用父类逻辑。
    • 可靠性:程序行为更可预测,避免因子类错误导致异常。
    • 解耦:高层模块无需关注具体子类实现。

3. 依赖倒置原则(Dependency Inversion Principle, DIP)

  • 定义

    • 高层模块不应该依赖低层模块,二者都应该依赖 抽象
    • 抽象不应该依赖细节,细节应该依赖抽象。
  • 核心思想

    • 面向接口编程:通过抽象(接口或抽象类)解耦模块间的依赖关系。
    • 减少耦合:高层模块不直接依赖底层实现,而是通过抽象接口间接调用。
  • 示例

    // 抽象接口(高层依赖)
    interface Database {void save();
    }// 具体实现(低层模块)
    class MySQL implements Database {public void save() {System.out.println("Saving to MySQL");}
    }// 高层模块(依赖抽象)
    class UserService {private Database database;public UserService(Database database) {this.database = database;}public void saveUser() {database.save();}
    }
    
  • 好处

    • 灵活性:可轻松切换底层实现(如从 MySQL 改为 PostgreSQL)。
    • 测试性:通过 Mock 抽象接口,方便单元测试。
    • 解耦:模块间依赖关系更清晰,降低维护成本。

4. 单一职责原则(Single Responsibility Principle, SRP)

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

    • 职责分离:一个类只负责一项功能,避免功能耦合。
  • 核心思想

    • 高内聚:将相关功能集中在一个类中。
    • 低耦合:不同职责分离到独立类中,减少相互影响。
  • 示例

    // 错误示例(违反 SRP)
    class User {private String name;private String email;// 职责1:用户信息管理public void setName(String name) { this.name = name; }// 职责2:邮件发送public void sendEmail(String message) {System.out.println("Sending email to " + email + ": " + message);}
    }// 改进方案(职责分离)
    class User {private String name;private String email;public void setName(String name) { this.name = name; }
    }class EmailService {public void sendEmail(String email, String message) {System.out.println("Sending email to " + email + ": " + message);}
    }
    
  • 好处

    • 易维护:修改一个功能时,不会影响其他职责。
    • 复用性:单一职责的类更容易被其他模块复用。
    • 可测试性:职责清晰的类更易编写单元测试。

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

  • 定义:客户端不应该依赖它不需要的接口。

    • 接口小型化:提供多个细粒度的接口,避免“胖接口”。
  • 核心思想

    • 按需依赖:客户端仅依赖其实际需要的方法。
    • 避免冗余:减少接口中不必要方法的暴露。
  • 示例

    // 错误示例(“胖”接口)
    interface Animal {void eat();     // 所有动物都需要void fly();     // 仅鸟类需要void swim();    // 仅鱼类需要
    }// 改进方案(接口隔离)
    interface Eatable {void eat();
    }interface Flyable {void fly();
    }interface Swimmable {void swim();
    }class Bird implements Eatable, Flyable {public void eat() { System.out.println("Bird eats"); }public void fly() { System.out.println("Bird flies"); }
    }class Fish implements Eatable, Swimmable {public void eat() { System.out.println("Fish eats"); }public void swim() { System.out.println("Fish swims"); }
    }
    
  • 好处

    • 减少依赖:客户端仅需关注所需接口。
    • 灵活性:接口组合更灵活,适应不同需求。
    • 可扩展性:新增功能时,只需扩展特定接口。

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

  • 定义:一个对象应尽可能少地了解其他对象。

    • 最少知识原则:只与直接朋友通信,避免跨层依赖。
  • 核心思想

    • 降低耦合:对象之间交互仅限于必要的依赖。
    • 封装细节:隐藏内部实现,通过接口暴露行为。
  • 示例

    // 错误示例(违反 LoD)
    class Manager {public void manage(Employee employee) {System.out.println("Manager manages employee: " + employee.getName());}
    }class Employee {private String name;public String getName() { return name; }
    }class Client {public void doWork() {Employee employee = new Employee();Manager manager = new Manager();manager.manage(employee); // 正确:Manager 直接依赖 Employee}
    }// 更复杂的错误示例(跨层依赖)
    class Client {public void doWork() {Department department = new Department();Employee employee = department.getEmployee(0);Manager manager = new Manager();manager.manage(employee); // 错误:Client 间接依赖 Employee}
    }
    
  • 好处

    • 松耦合:模块间依赖更清晰,减少连锁修改。
    • 可维护性:代码结构更简洁,易于理解和调试。
    • 稳定性:减少因依赖变更导致的连锁反应。

7. 合成/聚合复用原则(Composite Reuse Principle, CRP)

  • 定义:尽量使用 对象组合/聚合,而不是继承来达到复用目的。

    • 组合优先于继承:通过组合实现功能扩展,避免继承的强耦合。
  • 核心思想

    • 灵活性:组合允许动态替换实现,继承是静态的。
    • 减少继承层级:避免多层继承导致的复杂性和脆弱性。
  • 示例

    // 错误示例(继承)
    class Car {void start() { System.out.println("Car starts"); }
    }class SportsCar extends Car {void start() { System.out.println("SportsCar starts with V8 engine"); }
    }// 改进方案(组合)
    interface Engine {void start();
    }class V8Engine implements Engine {public void start() { System.out.println("V8 Engine starts"); }
    }class Car {private Engine engine;public Car(Engine engine) {this.engine = engine;}void start() {engine.start(); // 通过组合调用}
    }
    
  • 好处

    • 灵活性:可动态切换实现(如 Car 支持多种 Engine)。
    • 降低耦合:避免继承导致的强依赖关系。
    • 代码复用性:通过组合复用多个独立组件。

七大原则的核心价值总结

原则名称核心目标关键实践
开闭原则对扩展开放,对修改关闭抽象层封装变化
里氏替换子类替换父类不影响程序行为遵循父类契约
依赖倒置高层依赖抽象,低层实现细节面向接口编程
单一职责一个类只负责一项职责职责分离,高内聚
接口隔离提供最小接口,避免冗余细粒度接口,按需依赖
迪米特法则减少对象间直接交互封装细节,最少知识
合成复用优先组合而非继承通过组合实现灵活扩展

常见的设计模式有哪些?

设计模式类型设计模式名称核心作用适用场景
创建型单例模式保证唯一实例资源管理、全局访问
创建型工厂方法解耦对象创建动态选择实现
创建型抽象工厂创建相关对象族跨平台UI、产品族生成
创建型建造者分阶段构建复杂对象配置复杂对象
创建型原型复制现有对象高性能对象创建
结构型适配器兼容接口集成遗留系统
结构型装饰器动态扩展功能功能组合
结构型代理控制访问权限控制、延迟加载
结构型组合树形结构文件系统、菜单
结构型桥接解耦抽象与实现多维变化系统
结构型外观简化接口复杂系统简化
结构型享元共享对象内存优化
行为型策略动态切换算法支付方式、排序算法
行为型观察者事件通知消息订阅、GUI事件
行为型命令封装请求撤销/重做、任务队列
行为型模板方法定义算法骨架测试框架、流程固定
行为型迭代器遍历集合统一访问不同数据结构
行为型责任链传递请求审批流程、过滤器链
行为型备忘录恢复状态撤销操作、状态快照
行为型状态状态驱动行为订单状态机、游戏状态
行为型访问者分离操作与数据结构编译器、数据分析
行为型中介者减少对象间依赖聊天室、协调复杂交互
行为型解释器解析语言正则表达式、自定义DSL

关于设计模式的详细内容将在后续专门介绍,如需了解,可以关注一下后续文章。

http://www.dtcms.com/a/356863.html

相关文章:

  • 编程速递:RAD Studio 13 即将到来的功能
  • Linux应用软件编程--->数据库
  • C++函数继承
  • 【C++闯关笔记】STL:vector的学习与使用
  • 论文阅读:ICLR 2024 GAIA: A Benchmark for General AI Assistants
  • DBeaver中禁用PostgreSQL SSL的配置指南
  • SQL Server 查看备份计划
  • Creed —— 设置玩家属性(生命/耐力/经验值等)
  • 初学python的我开始Leetcode题-17
  • Azure Marketplace 和 Microsoft AppSource的区别
  • 订餐后台管理系统 -day03 登录模块
  • Linux操作系统Shell脚本-第一章
  • 数据防泄与最小可见:ABP 统一封装行级安全(RLS)+ 列级脱敏
  • 前端vue3入门学习
  • 数据分析编程第七步:分析与预测
  • 【MFC自动生成的文件详解:YoloClassMFC.cpp 的逐行解释、作用及是否能删除】
  • 科技赋能医疗:陪诊小程序系统开发,让就医不再孤单
  • cursor的setting設置換行
  • 舰用燃气机数字孪生:舰船动力智慧管控核心
  • 从0到1玩转 Google SEO
  • 循环高级(1)
  • Parasoft赋能测试:精准捕捉运行时缺陷
  • 深度学习入门Day10:深度强化学习原理与实战全解析
  • 彻底弄清URI、URL、URN的关系
  • 基于LangChain框架搭建AI问答系统(附源码)
  • 将2D基础模型(如SAM/SAM2)生成的2D语义掩码通过几何一致性约束映射到3D高斯点云
  • android 不同分辨图片放错对应文件夹会怎样?
  • Python 编码与加密全解析:从字符编码到 RSA 签名验证
  • (笔记)Android ANR检测机制深度分析
  • 【微知】如何撤销一个git的commit?以及撤销的3种方式?