文章目录

  • 什么是设计模式?
  • 为什么使用设计模式?
  • 设计模式的核心设计原则是什么?
    • 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.pswp.cn/news/920869.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/920869.shtml
英文地址,请注明出处:http://en.pswp.cn/news/920869.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络层和数据链路层

目录 1.网络层 2.数据链路层 1.网络层 我们知道,我们的消息为了从A端发送到B端,达成远距离传输,我们为此设计了很多协议层,分别是应用层,传输层,网络层,数据链路层,网卡&#xff0c…

Redis 的字典:像智能文件柜一样高效的哈希表实现

目录 一、从传统查找的痛点到哈希表的优势​ 二、哈希表的核心结构:文件柜的构成​ 2.1、 dictht 结构体:文件柜本体​ 2.2、dictEntry 结构体:带链条的文件夹​ 2.2.1、 哈希冲突的解决:抽屉里的链条​ 2.3、字典的高层封装…

FAST API部署和使用

第一部分:FastAPI 的使用(开发环境) 1. 安装 首先,你需要安装 FastAPI 和一个 ASGI 服务器,最常用的是 Uvicorn。 pip install "fastapi[standard]"这个命令会安装 FastAPI 以及所有推荐的依赖,包…

【JavaWeb】之HTML(对HTML细节的一些总结)

大家天天开心! 文章目录 前言一、HTML的简介二、HTML运行方式三、html 的标签/元素-说明四、表单注意事项总结 前言 首先我们在把Java基础学习完之后,我们就要进行网站方面的开发了,我们要了解网页的组成,而网页的组成有HTML,CSS,…

互联网医院品牌IP的用户体验和生态构建

一、患者体验与信任构建互联网医院品牌IP的价值核心在于获得患者的深度信任,而卓越的用户体验是实现这一目标的关键路径。在医疗服务同质化严重的当下,患者体验已成为医疗机构差异化竞争的重要维度。研究表明,良好的用户体验能够提高用户满意…

【Node.js教程】Express框架入门:从搭建到动态渲染商品列表

前言 Visual Studio Code(简称VSCode)是微软开发的一款免费开源跨平台代码编辑器,凭借其免费、开源、跨平台的特性,以及丰富的插件生态和美观的界面,成为前端开发者的首选工具。 本文将带你从零开始学习Express框架,包括搭建项目、配置路由、使用中间件以及实现动态渲染…

众擎机器人开源代码解读

一,综述 EngineAI ROS 包: 高层开发模式:用户可通过发布身体速度指令,直接调用 EngineAI 机器人的行走控制器。底层开发模式:用户可通过发布关节指令,自主开发专属的控制器。 ROS2 package:全…

Windows系统安装Git详细教程

文章目录步骤 1:下载 Git 安装包步骤 2:运行安装程序步骤 3:选择安装路径步骤 4:选择组件步骤 5:选择默认编辑器步骤 6:选择路径环境变量步骤 7:选择 HTTPS 协议的传输方式步骤 8:配…

leetcode 3446. 按对角线进行矩阵排序 中等

给你一个大小为 n x n 的整数方阵 grid。返回一个经过如下调整的矩阵:左下角三角形(包括中间对角线)的对角线按 非递增顺序 排序。右上角三角形 的对角线按 非递减顺序 排序。示例 1:输入: grid [[1,7,3],[9,8,2],[4,…

携程旅行 web 验证码 分析

声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 逆向分析 部分python代码 result cp…

JavaEE 进阶第一期:开启前端入门之旅(上)

专栏:JavaEE 进阶跃迁营 个人主页:手握风云 一、HTML基础 1.1. 什么是HTML HTML(Hyper Text Markup Language),超文本标记语言。 超文本:比文本要强大,通过链接和交互式方式来组织和呈现信息的文本形式。不仅仅有文本…

4.5 PBR

1.PBR简介 2.高光工作流 3.金属工作流1.PBR简介 PBR(Physically Based Rendering, 基于物理的渲染)的工作流分为金属工作流和高光工作流2.高光工作流 高光工作流是一种传统的工作流, 现在用的相对较少, 但是在某些特定情况下能提供更精细的控制a.核心思想它不区分金属和非金属,…

09.《路由基础知识解析和实践》

09.路由基础 文章目录09.路由基础核心概念路由关键组成部分三层转发原理介绍(通信流程)路由类型及配置直连路由(direct)实验示例**静态路由(Static)****实验示例****动态路由****RIP(routing information protocol---路…

websocket建立连接过程

1. 客户端发送一个GET的http请求,请求头要包含connection: upgradehost:localhost:8000。表明地址upgrade: websocket。指明升级的协议sec-websocket-key 。 安全验证密钥sec-websocket-version。 协议版本sec-websocket-accept 。对传过来的key进行加密…

Simulink库文件-一种低通滤波模块搭建方法

在汽车电控系统应用层开发中,经常会用到低通滤波模块,其主要作用是去除输入信号中的高频干扰,防止由于输入信号的干扰引起后续执行系统的非预期频繁波动。本文介绍简要介绍低通滤波的定义及作用,并介绍一种低通滤波模块simulink搭…

【C++游记】AVL树

枫の个人主页 你不能改变过去,但你可以改变未来 算法/C/数据结构/C Hello,这里是小枫。C语言与数据结构和算法初阶两个板块都更新完毕,我们继续来学习C的内容呀。C是接近底层有比较经典的语言,因此学习起来注定枯燥无味&#xf…

音视频学习(六十二):H264中的SEI

什么是SEI? 在 H.264 视频编码标准中,补充增强信息(Supplemental Enhancement Information,SEI) 是一种特殊的 NAL(网络抽象层)单元。它不像序列参数集(SPS)或图像参数集&#xff0…

docker run 后报错/bin/bash: /bin/bash: cannot execute binary file总结

以下方法来源于AI&#xff0c;个人仅验证了第三条便成功执行 1. 镜像与宿主机架构不匹配 比如&#xff1a; 你是 x86_64 的机器&#xff0c;但镜像是 ARM64 的&#xff08;或反之&#xff09;。在 PC 上拉了树莓派用的镜像。查看镜像架构 docker inspect <image_name> | …

【Redisson 加锁源码解析】

Redisson 源码解析 —— 分布式锁实现过程 在分布式系统中&#xff0c;分布式锁 是非常常见的需求&#xff0c;用来保证多个节点之间的互斥操作。Redisson 是 Redis 的一个 Java 客户端&#xff0c;它提供了对分布式锁的良好封装。本文将从源码角度剖析 Redisson 的分布式锁实现…

uni-app支持单多选、搜索、查询、限制能否点击组件

<template><view class="multi-select-container" :class="{ single-select: !multiple, no-search: !searchable }"><!-- 当组件被禁用时,直接显示选中的内容 --><view class="disabled-display" v-if="disabled &a…