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

文章目录

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

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

什么是设计模式?

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

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


为什么使用设计模式?

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

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

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

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

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

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

    java 复制代码
    // 抽象接口(稳定层)
    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)

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

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

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

    java 复制代码
    // 父类
    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)

  • 定义

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

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

    java 复制代码
    // 抽象接口(高层依赖)
    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)

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

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

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

    java 复制代码
    // 错误示例(违反 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)

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

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

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

    java 复制代码
    // 错误示例("胖"接口)
    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)

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

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

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

    java 复制代码
    // 错误示例(违反 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)

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

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

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

    java 复制代码
    // 错误示例(继承)
    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

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

相关推荐
Eiceblue9 分钟前
Java实现PDF表格转换为CSV
java·python·pdf
自由的疯1 小时前
Java RuoYi整合Magic-Api详解
java·后端·架构
老华带你飞1 小时前
校园二手书交易|基于SprinBoot+vue的校园二手书交易管理系统(源码+数据库+文档)
java·前端·数据库·vue.js·小程序·毕设·校园二手书交易管理系统
hoho不爱喝酒1 小时前
微服务Eureka组件的介绍、安装、使用
java·微服务·eureka·架构
华仔啊2 小时前
接口卡成PPT?这9个优化技巧让系统飞起来,亲测有效!
java
华仔啊2 小时前
别再乱 new ArrayList!8 大 Java 容器选型案例,一篇看懂
java·后端
ssshooter2 小时前
上下文工程:为高级大型语言模型构建信息环境
人工智能·算法·设计模式
我也要当昏君2 小时前
5.2 I/O软件
java·网络·算法
阿鹿.3 小时前
docker-相关笔记
java·笔记·docker