设计模式理解
一、对设计模式的理解
1. 什么是设计模式?
官方定义:设计模式(Design Pattern)是一套被反复使用、多数人知晓、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中一些不断重复发生的问题,以及该问题的解决方案的核心。
2. 为什么要学习设计模式?
-
代码复用性(Reusability):模式提供了已经测试和验证过的设计模板,避免重复造轮子。
-
代码可扩展性(Extensibility):模式指导我们设计出松耦合的结构,当系统需要增加新功能时,影响最小,符合开闭原则(对扩展开放,对修改关闭)。
-
代码可维护性(Maintainability):模式使代码结构清晰、层次分明,易于阅读和理解。后人维护时,能快速找到相关模块,降低维护成本。
-
代码灵活性(Flexibility):通过接口和抽象,使得组件可以方便地被替换和组合,应对多变的需求。
3. 设计模式的六大原则
-
开闭原则(OCP):对扩展开放,对修改关闭。这是终极目标。通过扩展(如继承、实现接口)来添加新功能,而不是修改已有的源代码。
-
单一职责原则(SRP):一个类只负责一项职责。避免一个类变得过于庞大和难以修改。
-
里氏替换原则(LSP):所有引用基类(父类)的地方必须能透明地使用其子类的对象。即子类可以扩展父类的功能,但不能改变父类原有的功能。
-
依赖倒置原则(DIP):要依赖于抽象,而不是具体实现。
-
高层模块不应依赖低层模块,二者都应依赖于抽象。
-
抽象不应依赖于细节,细节应依赖于抽象。
-
-
接口隔离原则(ISP):客户端不应该被迫依赖于它不使用的接口。将一个庞大的接口拆分成更小、更具体的接口。
-
迪米特法则(LoD):又称最少知识原则。一个对象应该对其他对象有最少的了解。只与直接的朋友通信,降低类之间的耦合。
二、在日常开发中运用设计模式
核心思想:重构优于预先设计(Refactoring to Patterns)
切忌为了用模式而用模式。正确的使用姿势是:
-
先写出可工作的代码:首先,用最直接、最简单的方式实现功能需求。
-
识别“不同写法的缺点”:在编写或Review代码时,警惕以下“缺点”:
-
冗长的if-else/switch分支(可能需用策略模式、状态模式)
-
直接new一个对象,依赖具体类(可能需用工厂方法、抽象工厂)
-
一个类过于庞大,做了太多事(违反单一职责原则,需拆分类)
-
多个类有相同的行为,只是实现不同(可能需用模板方法模式)
-
对象间的依赖关系复杂混乱(可能需用中介者模式)
-
需要为其他对象提供一种代理以控制对这个对象的访问(可能需用代理模式)
-
-
思考能否用模式重构:当发现上述“缺点”时,思考哪种设计模式可以优雅地解决这个问题。
-
权衡利弊:评估引入模式带来的好处(扩展性、清晰度)和代价(复杂度、类数量)。如果当前需求非常稳定,且简单实现完全够用,就不要过度设计。
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 {
@Override
public void share(Content content) {
// 调用微信SDK的具体API
System.out.println("[策略] 分享到微信好友: " + content.getSummary());
}
}
public class WeChatMomentStrategy implements ShareStrategy {
@Override
public void share(Content content) {
// 同样是微信,但可以是分享到朋友圈的不同策略
System.out.println("[策略] 分享到微信朋友圈: " + content.getSummary());
}
}
public class QQStrategy implements ShareStrategy {
@Override
public void share(Content content) {
// 调用QQ SDK的具体API
System.out.println("[策略] 分享到QQ: " + content.getSummary());
}
}
public class WeiboStrategy implements ShareStrategy {
@Override
public void share(Content content) {
// 调用微博SDK的具体API
System.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方法)。
更多推荐
所有评论(0)