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

设计模式理解

一、对设计模式的理解

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.dtcms.com/a/354195.html

相关文章:

  • Nishang PowerShell工具:原理详解+使用方法+渗透实战
  • Go+Gdal 完成高性能GIS数据空间分析
  • 深度学习:常用的损失函数的使用
  • “java简单吗?”Java的“简单”与PHP的挑战:编程语言哲学-优雅草卓伊凡
  • 白话FNN、RNN、Attention和self-attention等
  • 《从有限元到深度学习:我的金属疲劳研究进阶之路》
  • 反内卷加速全产业链价值重塑 通威股份等行业龙头或率先受益
  • 基于 C# OpenCVSharp 的模板匹配检测技术方案
  • 计算机日常答疑,一起寻找问题的最优解
  • select
  • SM4加密算法
  • Karatsuba
  • 前端工程化与AI融合:构建智能化开发体系
  • 4-4.Python 数据容器 - 字典 dict(字典 dict 概述、字典的定义与调用、字典的遍历、字典的常用方法)
  • CPU 虚拟化之Cpu Models
  • 代码随想录刷题Day43
  • 时间轮定时器HashedWheelTimer
  • WSL设置静态IP
  • window程序打包
  • Libvio网站与客户端访问故障排查指南(专业版)
  • 什么是低空经济?
  • JMeter 5.3 性能测试:文件下载脚本编写与导出文件接收完整指南
  • QT鼠标事件中的QMouseEvent :e
  • 深度学习---卷积神经网络CNN
  • PLC_博图系列☞基本指令”S_ODT:分配接通延时定时器参数并启动“
  • HTML5超详细学习内容
  • 程序(进程)地址空间(1)
  • 基于MATLAB/Simulink的单机带负荷仿真系统搭建
  • LeetCode-23day:技巧经典
  • 疯狂星期四文案网第52天运营日记