news 2026/1/10 10:09:36

设计模式详解:代码架构的艺术

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
设计模式详解:代码架构的艺术

设计模式是解决特定上下文中重复出现的问题的通用、可重用的解决方案模板,是软件工程领域的宝贵经验总结。

一、设计模式分类概览

创建型模式(5种):对象创建的艺术

  • 单例模式:确保一个类只有一个实例

  • 工厂方法:创建对象但不指定具体类

  • 抽象工厂:创建相关对象家族

  • 建造者:分步构建复杂对象

  • 原型:通过复制创建对象

结构型模式(7种):对象组合的艺术

  • 适配器:兼容不同接口

  • 装饰器:动态添加功能

  • 代理:控制对象访问

  • 外观:简化复杂子系统

  • 桥接:分离抽象与实现

  • 组合:树形结构处理

  • 享元:共享小对象节省内存

行为型模式(11种):对象交互的艺术

  • 策略:封装可互换的算法

  • 观察者:一对多的依赖关系

  • 模板方法:定义算法骨架

  • 迭代器:顺序访问集合元素

  • 责任链:传递请求的链

  • 命令:封装请求为对象

  • 备忘录:保存和恢复状态

  • 状态:封装状态相关行为

  • 访问者:分离算法与结构

  • 中介者:减少对象间耦合

  • 解释器:定义语言文法

二、设计原则(SOLID)

1. 单一职责原则(SRP)

// ❌ 违反SRP - 一个类承担多个职责 class UserManager { createUser(user) { // 验证逻辑 // 保存到数据库 // 发送欢迎邮件 // 更新统计信息 } } // ✅ 遵守SRP - 每个类只有一个职责 class UserValidator { validate(user) { /* 验证逻辑 */ } } class UserRepository { save(user) { /* 数据库操作 */ } } class EmailService { sendWelcome(user) { /* 发送邮件 */ } } class StatisticsService { update(user) { /* 更新统计 */ } }

2. 开闭原则(OCP)

// ✅ 对扩展开放,对修改关闭 class Discount { getDiscount(amount) { return amount * 0.1; // 默认10%折扣 } } class PremiumDiscount extends Discount { getDiscount(amount) { return amount * 0.2; // 高级用户20%折扣 } } class VIPDiscount extends Discount { getDiscount(amount) { return amount * 0.3; // VIP用户30%折扣 } } // 新增折扣类型时不需要修改现有代码 class BlackFridayDiscount extends Discount { getDiscount(amount) { return amount * 0.5; // 黑五50%折扣 } }

3. 里氏替换原则(LSP)

// ✅ 子类可以替换父类 class Bird { move() { console.log('移动'); } } class FlyingBird extends Bird { fly() { console.log('飞行'); } } class Penguin extends Bird { move() { console.log('游泳'); } // 企鹅用游泳替代移动 } function makeBirdMove(bird) { bird.move(); // 可以传入任何Bird子类 }

4. 接口隔离原则(ISP)

// ❌ 违反ISP - 臃肿的接口 interface Worker { work(); eat(); sleep(); } // ✅ 遵守ISP - 细分的接口 interface Workable { work(); } interface Eatable { eat(); } interface Sleepable { sleep(); } class Human implements Workable, Eatable, Sleepable { work() { /* 工作 */ } eat() { /* 吃饭 */ } sleep() { /* 睡觉 */ } } class Robot implements Workable { work() { /* 工作 */ } }

5. 依赖倒置原则(DIP)

// ✅ 依赖抽象,而不是具体实现 // 抽象层 interface Database { save(data); } // 具体实现 class MySQLDatabase implements Database { save(data) { /* MySQL实现 */ } } class MongoDB implements Database { save(data) { /* MongoDB实现 */ } } // 高层模块依赖抽象 class UserService { constructor(database: Database) { this.database = database; } createUser(user) { // 业务逻辑... this.database.save(user); } }

三、模式选择决策树

四、关键模式详解

1. 工厂方法模式

// 产品接口 class Transport { deliver() {} } // 具体产品 class Truck extends Transport { deliver() { return "陆路运输"; } } class Ship extends Transport { deliver() { return "海运"; } } // 创建者 class Logistics { planDelivery() { const transport = this.createTransport(); console.log(`计划: ${transport.deliver()}`); } createTransport() { throw new Error("必须实现"); } } // 具体创建者 class RoadLogistics extends Logistics { createTransport() { return new Truck(); } } class SeaLogistics extends Logistics { createTransport() { return new Ship(); } } // 使用 const roadLogistics = new RoadLogistics(); roadLogistics.planDelivery(); // 输出: 计划: 陆路运输

2. 观察者模式

class Subject { constructor() { this.observers = []; } subscribe(observer) { this.observers.push(observer); } unsubscribe(observer) { const index = this.observers.indexOf(observer); if (index > -1) this.observers.splice(index, 1); } notify(data) { this.observers.forEach(observer => observer.update(data)); } } class Observer { update(data) {} } // 具体实现 class NewsPublisher extends Subject { publish(news) { console.log(`发布新闻: ${news}`); this.notify(news); } } class Subscriber extends Observer { constructor(name) { super(); this.name = name; } update(news) { console.log(`${this.name} 收到新闻: ${news}`); } } // 使用 const publisher = new NewsPublisher(); const subscriber1 = new Subscriber("用户A"); const subscriber2 = new Subscriber("用户B"); publisher.subscribe(subscriber1); publisher.subscribe(subscriber2); publisher.publish("今日头条新闻");

3. 装饰器模式

class Coffee { cost() { return 5; } description() { return "普通咖啡"; } } class CoffeeDecorator { constructor(coffee) { this.coffee = coffee; } cost() { return this.coffee.cost(); } description() { return this.coffee.description(); } } class MilkDecorator extends CoffeeDecorator { cost() { return this.coffee.cost() + 2; } description() { return this.coffee.description() + " + 牛奶"; } } class SugarDecorator extends CoffeeDecorator { cost() { return this.coffee.cost() + 1; } description() { return this.coffee.description() + " + 糖"; } } // 使用 let myCoffee = new Coffee(); console.log(`${myCoffee.description()}: $${myCoffee.cost()}`); myCoffee = new MilkDecorator(myCoffee); console.log(`${myCoffee.description()}: $${myCoffee.cost()}`); myCoffee = new SugarDecorator(myCoffee); console.log(`${myCoffee.description()}: $${myCoffee.cost()}`);

4. 策略模式

class PaymentStrategy { pay(amount) {} } class CreditCardPayment extends PaymentStrategy { constructor(cardNumber) { super(); this.cardNumber = cardNumber; } pay(amount) { console.log(`信用卡支付 $${amount}`); } } class PayPalPayment extends PaymentStrategy { constructor(email) { super(); this.email = email; } pay(amount) { console.log(`PayPal支付 $${amount}`); } } class ShoppingCart { constructor() { this.items = []; this.paymentStrategy = null; } setPaymentStrategy(strategy) { this.paymentStrategy = strategy; } checkout() { const total = this.items.reduce((sum, item) => sum + item.price, 0); this.paymentStrategy.pay(total); } }

5. 单例模式

// 懒汉式单例 class Logger { constructor() { if (Logger.instance) { return Logger.instance; } this.logs = []; Logger.instance = this; return this; } log(message) { const timestamp = new Date().toISOString(); this.logs.push(`${timestamp}: ${message}`); console.log(message); } getLogs() { return this.logs; } } // 使用 const logger1 = new Logger(); const logger2 = new Logger(); logger1.log("第一条日志"); logger2.log("第二条日志"); console.log(logger1 === logger2); // true console.log(logger1.getLogs()); // 包含两条日志

五、设计模式应用场景

Web开发中的应用

// React Hooks中的状态管理(观察者模式) const [state, setState] = useState(initialState); // Redux中的状态管理(单例+观察者) const store = createStore(reducer); store.subscribe(() => { const state = store.getState(); // 更新UI }); // Express中间件(责任链模式) app.use((req, res, next) => { // 认证中间件 next(); }); app.use((req, res, next) => { // 日志中间件 next(); }); // Vue/React组件(组合模式) <App> <Header /> <Main> <Sidebar /> <Content /> </Main> <Footer /> </App>

六、反模式识别

常见反模式

  1. 上帝对象(God Object)

    // ❌ 一个类做所有事情 class GodClass { validateUser() {} sendEmail() {} saveToDB() {} generateReport() {} processPayment() {} }
  2. 重复代码

    // ❌ 相同的代码出现在多个地方 function calculateTax1(amount) { return amount * 0.1 + amount * 0.05; } function calculateTax2(amount) { return amount * 0.1 + amount * 0.05; }
  3. 过度设计

    // ❌ 为简单的需求使用复杂的模式 // 不需要工厂模式的情况 class SimpleObjectFactory { createObject(type) { switch(type) { case 'A': return new A(); case 'B': return new B(); default: return new Default(); } } }

七、实践建议

何时使用设计模式?

场景

推荐模式

原因

需要全局访问点

单例模式

如配置管理、日志记录

需要创建复杂对象

建造者模式

如SQL查询构建器

需要不同算法策略

策略模式

如支付方式、排序算法

需要事件通知

观察者模式

如状态变更通知

需要动态添加功能

装饰器模式

如中间件、权限验证

需要简化复杂系统

外观模式

如API封装、SDK设计

代码质量检查清单

// 好的设计模式应用应该: // 1. 提高代码可读性 // 2. 降低耦合度 // 3. 提高可测试性 // 4. 便于扩展和维护 // 5. 遵循SOLID原则 // 自我检查问题: // - 这个模式是否解决了实际问题? // - 是否增加了不必要的复杂度? // - 是否符合团队的编码规范? // - 是否有更简单的解决方案?

八、学习路径建议

  1. 初级阶段:掌握单例、工厂、观察者、策略

  2. 中级阶段:理解装饰器、适配器、模板方法、命令

  3. 高级阶段:应用组合、访问者、中介者、状态

  4. 精通阶段:识别模式组合,避免过度设计

总结

设计模式不是银弹,而是工具。正确的使用方式是:

  • 理解问题本质,而不是生搬硬套

  • 保持简单,在必要时引入复杂模式

  • 关注原则,而不是具体实现

  • 持续重构,让模式自然浮现

模式服务于代码,而不是代码服务于模式。好的设计应该让代码更清晰、更易维护,而不是更复杂。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/9 19:43:56

开源通信应用终极配置指南:轻松实现安全通话与即时消息

开源通信应用终极配置指南&#xff1a;轻松实现安全通话与即时消息 【免费下载链接】linphone-android 项目地址: https://gitcode.com/gh_mirrors/li/linphone-android 在当今数字时代&#xff0c;寻找一款既安全又功能全面的通信应用变得尤为重要。Linphone作为一款优…

作者头像 李华
网站建设 2025/12/25 1:58:03

【精准农业数据分析】:基于R语言的回归诊断技术与应用案例

第一章&#xff1a;农业产量的 R 语言回归诊断在农业数据分析中&#xff0c;理解影响作物产量的关键因素至关重要。回归模型被广泛用于探索土壤质量、降水量、施肥量等变量与农作物产量之间的关系。然而&#xff0c;模型拟合后必须进行回归诊断&#xff0c;以确保其假设成立并提…

作者头像 李华
网站建设 2025/12/29 16:02:23

C++后台开发学习路线

找完工作后一直想找时间写点东西&#xff0c;回馈牛客&#xff0c;由于在忙各种事情&#xff0c;一直拖到现在。作为一个19届的老油条&#xff0c;趁在毕业之前&#xff0c;将我的学习总结分享给大家&#xff0c;希望对正在找实习或者找工作的同学有所帮助。个人介绍首先介绍下…

作者头像 李华
网站建设 2025/12/30 16:03:11

Springboot旅游信息网na6kf(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表项目功能&#xff1a;用户,景点分类,景点信息,酒店信息,航班信息,火车信息,客车信息,当地公交,旅游日志开题报告内容一、选题背景及意义&#xff08;一&#xff09;选题背景自改革开放以来&#xff0c;中国旅游业经历了起步、成长、拓展和综合发展四个阶段&…

作者头像 李华
网站建设 2026/1/7 19:26:58

C 语言运算符完全指南:从入门到避坑

阅读对象&#xff1a;C 语言初学者、在校学生、初级嵌入式/系统开发工程师 目标&#xff1a;不仅让你“记住”运算符&#xff0c;更让你“理解”代码背后的逻辑。如果把变量比作 C 语言中的“积木”&#xff0c;那么运算符就是粘合这些积木的“胶水”和“工具”。没有它们&…

作者头像 李华