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

设计模式理解

一、对设计模式的理解

1. 什么是设计模式?

官方定义:设计模式(Design Pattern)是一套被反复使用、多数人知晓、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中一些不断重复发生的问题,以及该问题的解决方案的核心

2. 为什么要学习设计模式?
  1. 代码复用性(Reusability):模式提供了已经测试和验证过的设计模板,避免重复造轮子。

  2. 代码可扩展性(Extensibility):模式指导我们设计出松耦合的结构,当系统需要增加新功能时,影响最小,符合开闭原则(对扩展开放,对修改关闭)。

  3. 代码可维护性(Maintainability):模式使代码结构清晰、层次分明,易于阅读和理解。后人维护时,能快速找到相关模块,降低维护成本。

  4. 代码灵活性(Flexibility):通过接口和抽象,使得组件可以方便地被替换和组合,应对多变的需求。

3. 设计模式的六大原则
  1. 开闭原则(OCP)对扩展开放,对修改关闭。这是终极目标。通过扩展(如继承、实现接口)来添加新功能,而不是修改已有的源代码。

  2. 单一职责原则(SRP):一个类只负责一项职责。避免一个类变得过于庞大和难以修改。

  3. 里氏替换原则(LSP):所有引用基类(父类)的地方必须能透明地使用其子类的对象。即子类可以扩展父类的功能,但不能改变父类原有的功能。

  4. 依赖倒置原则(DIP)要依赖于抽象,而不是具体实现

    • 高层模块不应依赖低层模块,二者都应依赖于抽象。

    • 抽象不应依赖于细节,细节应依赖于抽象。

  5. 接口隔离原则(ISP):客户端不应该被迫依赖于它不使用的接口。将一个庞大的接口拆分成更小、更具体的接口。

  6. 迪米特法则(LoD):又称最少知识原则。一个对象应该对其他对象有最少的了解。只与直接的朋友通信,降低类之间的耦合。


二、在日常开发中运用设计模式

核心思想:重构优于预先设计(Refactoring to Patterns)

切忌为了用模式而用模式。正确的使用姿势是:

  1. 先写出可工作的代码:首先,用最直接、最简单的方式实现功能需求。

  2. 识别“不同写法的缺点”:在编写或Review代码时,警惕以下“缺点”:

    • 冗长的if-else/switch分支(可能需用策略模式、状态模式

    • 直接new一个对象,依赖具体类(可能需用工厂方法、抽象工厂

    • 一个类过于庞大,做了太多事(违反单一职责原则,需拆分类)

    • 多个类有相同的行为,只是实现不同(可能需用模板方法模式

    • 对象间的依赖关系复杂混乱(可能需用中介者模式

    • 需要为其他对象提供一种代理以控制对这个对象的访问(可能需用代理模式

  3. 思考能否用模式重构:当发现上述“缺点”时,思考哪种设计模式可以优雅地解决这个问题。

  4. 权衡利弊:评估引入模式带来的好处(扩展性、清晰度)和代价(复杂度、类数量)。如果当前需求非常稳定,且简单实现完全够用,就不要过度设计。

e.g.

  • 最初支付功能可能用 if (type == "wechat") {...} else if (type == "alipay") {...}

  • 当新增一种支付方式时,你需要修改这个核心方法,违反了开闭原则

  • 此时识别到“坏味道”,就可以重构为策略模式,将每种支付算法封装成类,未来新增只需添加一个新策略类即可。


第三部分:场景题设计 - 多平台分享功能

场景:在抖音/小红书看到内容,可以分享到微信、QQ、微博等多个平台。

1. 模式选择与分析
  • 核心需求:将“分享”这个行为视为一个算法族。分享到微信、分享到QQ、分享到微博等都是这个行为的不同“策略”或“算法”。

  • 问题:我们希望在运行时能够灵活地选择使用哪一种分享策略,并且避免使用冗长的 if-else 或 switch 语句来判断平台。

  • 解决方案:使用策略模式。它定义了一系列的算法(策略),并将每一个算法封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户端。

2. 策略模式设计

UML 类图

流程图

3. 代码实现
// 1. 策略接口:定义分享算法族
public interface ShareStrategy {void share(Content content);
}// 2. 具体策略类:实现不同平台的分享算法
public class WeChatStrategy implements ShareStrategy {@Overridepublic void share(Content content) {// 调用微信SDK的具体APISystem.out.println("[策略] 分享到微信好友: " + content.getSummary());}
}public class WeChatMomentStrategy implements ShareStrategy {@Overridepublic void share(Content content) {// 同样是微信,但可以是分享到朋友圈的不同策略System.out.println("[策略] 分享到微信朋友圈: " + content.getSummary());}
}public class QQStrategy implements ShareStrategy {@Overridepublic void share(Content content) {// 调用QQ SDK的具体APISystem.out.println("[策略] 分享到QQ: " + content.getSummary());}
}public class WeiboStrategy implements ShareStrategy {@Overridepublic void share(Content content) {// 调用微博SDK的具体APISystem.out.println("[策略] 分享到微博: " + content.getSummary());}
}
// 未来新增小红书分享,只需新增一个策略类:XiaohongshuStrategy// 3. 环境上下文类 (Context):负责持有和使用策略
public class ShareContext {// 持有策略接口的引用,而非具体实现private ShareStrategy strategy;// 设置当前需要使用的策略(Setter注入,非常灵活)public void setStrategy(ShareStrategy strategy) {this.strategy = strategy;}// 执行分享操作public void executeShare(Content content) {if (strategy == null) {System.out.println("请先设置分享策略");return;}// 将工作委托给当前设置的策略对象strategy.share(content);}
}// 4. 内容类(不变)
public class Content {private String title;private String image;private String url;public String getSummary() {return title + " - " + url;}// getters and setters...
}// 5. 客户端使用
public class Client {public static void main(String[] args) {// 准备分享内容Content content = new Content();content.setTitle("这个视频太搞笑了!");content.setUrl("https://www.douyin.com/video/456");// 创建分享上下文ShareContext shareContext = new ShareContext();// 用户选择分享到微信shareContext.setStrategy(new WeChatStrategy());shareContext.executeShare(content);// 用户改变主意,要分享到微博shareContext.setStrategy(new WeiboStrategy());shareContext.executeShare(content);// 也可以结合简单工厂模式,避免客户端直接new具体策略String userChoice = "wechat_moment"; // 可以从UI点击事件获取ShareStrategy strategy = StrategyFactory.getStrategy(userChoice);shareContext.setStrategy(strategy);shareContext.executeShare(content);}
}// 可选:策略工厂,进一步解耦客户端与具体策略
class StrategyFactory {public static ShareStrategy getStrategy(String platform) {switch (platform) {case "wechat": return new WeChatStrategy();case "wechat_moment": return new WeChatMomentStrategy();case "qq": return new QQStrategy();case "weibo": return new WeiboStrategy();default: throw new IllegalArgumentException("不支持的平台: " + platform);}}
}
4. 设计优势与对比
  • 符合开闭原则:新增一个分享平台(如小红书)时,只需添加一个新的 XiaohongshuStrategy 类,无需修改任何现有的策略类或上下文类。

  • 消除了条件判断:客户端(如UI层)通过设置不同的策略对象来指定行为,避免了在业务代码中出现庞大的 if-else 分支。

  • 灵活性极高:可以在运行时动态地改变对象的行为(通过 setStrategy 方法)。

http://www.xdnf.cn/news/19028.html

相关文章:

  • Shader开发(十七)着色器中的纹理采样与渲染
  • 农业物联网:科技赋能现代农业新篇章
  • 数模笔记day01(数据预处理、K-means聚类、遗传算法、概率密度分布)
  • UE5蓝图接口的创建和使用方法
  • 有鹿机器人如何用科技与创新模式破解行业难题
  • linux下的网络编程(2)
  • 智能体协作体系核心逻辑:Prompt、Agent、Function Calling 与 MCP 解析
  • AV1到达开始和约束时间
  • 分治法——二分答案
  • XFile v2 系统架构文档
  • Ansible 核心模块与实操练习
  • 第十三章项目资源管理--13.3 规划资源管理
  • Apifox 8 月更新|新增测试用例、支持自定义请求示例代码、提升导入/导出 OpenAPI/Swagger 数据的兼容性
  • 手写MyBatis第37弹: 深入MyBatis MapperProxy:揭秘SQL命令类型与动态方法调用的完美适配
  • AI赋能前端性能优化:核心技术与实战策略
  • Swift 解法详解 LeetCode 364:嵌套列表加权和 II
  • 713 乘积小于k的子数组
  • git学习 分支管理(branching)合并分支
  • golang13 单元测试
  • Office 2024 长期支持版(Mac中文)Word、Execl、PPT
  • Node.js 多版本管理工具 nvm 的安装与使用教程(含镜像加速与常见坑)
  • 共识算法如何保障网络安全
  • Java全栈开发面试实战:从基础到微服务的深度探索
  • k8s集群Prometheus部署
  • 1 vs 10000:如何用AI智能体与自动化系统,重构传统销售客户管理上限?
  • Wi-Fi数据包发送机制:从物理层到MAC层的深度解析
  • 记录使用ruoyi-flowable开发部署中出现的问题以及解决方法(二)
  • 贴片式TE卡 +北京君正+Rk瑞芯微的应用
  • 直线拟合方法全景解析:最小二乘、正交回归与 RANSAC
  • Transformer实战(15)——使用PyTorch微调Transformer语言模型