「趣学前端」设计模式学习与应用

简介: 用技术实现梦想,用梦想打开创意之门。今天分享设计模式学习与应用。

一、前言

我开始几年的开发中几乎没有使用过设计模式。前端常见的设计模式,我看过好几遍,模式名称记得很清楚,但是具体内容和原理,我印象很模糊。

之所以记不住,用不上,原因两点,大部分功能比较简单,开发时也就用简单的方案进行实现了;对设计模式的理解没有透彻,不会用。

我感觉自己最近有高效率学习的buff,所以试着重新理解这个知识点。


二、边学边用

之前学习新技术的时候,看一遍文档或者文章,记忆并不深刻,后来发现自己对新技术的掌握程度在于自己是否真实的实现过。也就是常说的“好记性不如烂笔头”。而且我不擅长过目不忘,我需要理解了才能更好的记忆。

对于前端设计模式的学习,我采用了知识点介绍+功能代码的模式,方便学习、理解和记忆。其中知识点介绍大部分来自我参考的文章,参考文章会列在文章底部。(都是很优秀的文章)


2.1 外观模式

2.1.1 介绍

外观模式为子系统中的一组接口提供一个统一的高层接口,使子系统更容易使用。简而言之外观设计模式就是把多个子系统中复杂逻辑进行抽象,从而提供一个更统一、更简洁、更易用的API。


2.1.2 应用场景

很多我们常用的框架和库基本都遵循了外观设计模式。我们在实际开发中复杂的功能处理比如将某些复杂逻辑抽离进行封装,对外仅提供一个API即可,也是对外观模式的应用


2.1.3 简单小实例

我把之前做的功能简化了一下分享出来。

  • 三个私有方法分别是_userBaseInfo(获取用户基础信息)、_userAddressInfo(获取用户的订单信息)、_userOrderInfo(获取用户的收货地址);
  • 对外提供的方法是getUserInfo(获取用户的购物信息);
  • 将内部的数据处理封装成一个方法提供出来,这样一个外观模式就实现了。
/** * 用户-基础信息 */const_userBaseInfo= () => {
constobj= {
name: '张三',
phone: '123456',
sex: '男',
  };
returnobj;
};
/** * 用户-收货地址信息 */const_userAddressInfo= () => {
constobj= {
province: '北京市',
city: '北京市',
region: '昌平',
  };
returnobj;
};
/** * 用户-订单信息 */const_userOrderInfo= () => {
constobj= {
orderNo: '123',
price: '129',
goodName: '帽子',
  };
returnobj;
};
/** * 用户-购物信息 */constgetUserInfo= () => {
constbaseInfo=_userBaseInfo();
constaddressInfo=_userAddressInfo();
constorderInfo=_userOrderInfo();
constobj= {
...baseInfo,
...addressInfo,
...orderInfo,
  };
returnobj;
};
constuserInfo=getUserInfo();
console.log({ userInfo }); 
// 打印结果// {//   userInfo: {//     name: '张三',//     phone: '123456',//     sex: '男',//     province: '北京市',//     city: '北京市',//     region: '昌平',//     orderNo: '123',//     price: '129',//     goodName: '帽子'//   }// }


2.2 代理模式

2.2.1 介绍

代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。


2.2.2 应用场景

  • 一些内部类不想或者不能直接被外部引用,可以使用代理类作为和外部的连接;
  • 功能扩展,无需修改委托类,在代理类增加需要的功能就能实现功能扩展,比如增加消息通知、日志、缓存等。


2.2.3 简单小实例

  • 一般二手书网站提供购买和出售书籍两种交易方式;
  • 多抓鱼是我常用的二手书平台,它可以看做是一个代理服务,同时多抓鱼的配送服务使用的顺丰这种快速送货和取货的服务;
/** * 二手书网站 提供购买和出售两种交易方式 */classBookTrading {
// 购买图书buyBook(props) {
props=props?props : {};
letres='购买了'+props.amount+'本'+props.name;
console.log(res);
  }
// 出售图书recoveryBook(props) {
props=props?props : {};
letres='出售了'+props.amount+'本'+props.name;
console.log(res);
  }
}
/** * 多抓鱼二手书交易平台 */classDuozhuayuextendsBookTrading {
constructor() {
super();
  }
buy(props) {
// 购买图书this.buyBook(props);
  }
buyDelivery(props) {
// 购买图书console.log('顺丰一日送达:');
this.buyBook(props);
  }
recovery(props) {
// 出售图书this.buyBook(props);
  }
recoveryPickUp(props) {
console.log('顺丰上门取件:');
this.recoveryBook(props);
  }
}
constduozhuayu=newDuozhuayu();
duozhuayu.buy({ name: '书店日记', amount: 2 });
duozhuayu.buyDelivery({ name: '中国地理杂志', amount: 5 });
duozhuayu.recovery({ name: '乌合之众', amount: 1 });
duozhuayu.recoveryPickUp({ name: '局外人', amount: 1 });
// 打印结果// 购买了2本书店日记// 顺丰一日送达:// 购买了5本中国地理杂志// 购买了1本乌合之众// 顺丰上门取件:// 出售了1本局外人


2.3 观察者模式

2.3.1 介绍

观察者模式又称发布订阅模式(Publish/Subscribe Pattern),被观察对象(subject)维护一组观察者(observer),当被观察对象状态改变时,通过调用观察者的某个方法将这些变化通知到观察者。


2.3.2 应用场景

很多类似消息传递的场景都适用观察者模式,比如商品订阅到货提醒、招聘中的求职者和HR的通信等


2.3.3 简单小实例

以电商中商品到货提醒功能为例,这个小例子帮助我很好的理解了观察者模式。

观察者模式中,被观察者(Subject)和观察者(Observer)是必不可少的,整个使用过程都是它俩的信息置换。

被观察者Subject

  • 维护观察者列表。例子中即消费者列表。
  • 定义添加和取消观察的方法。例子中即提供给消费者添加到货提醒和取消到货提醒的功能;
  • 当监测到自身变化之后,通过调用自己的notice方法依次通知每一个有通知权限的观察者,例子中即添加了到货提醒的消费者。


观察者Observer:

  • 定义update方法,提供给被观察者调用。例子中即到货之后消费者接收的通知消息。
  • 自定义方法,实现业务逻辑。例子中即添加了到货通知的消费者实际接收到的消息内容。

流程图如下:

image.jpeg

定义观察者类

// 观察者classObserver {
constructor(name) {
this.name=name;
  }
update(info) {
// 只有添加到货通知权限的才进行到货提醒if (info.notifyType==='add') {
this.remindArrival(info.goodName);
    } elseif (info.notifyType==='cancel') {
console.log(`${this.name}取消到货提醒,不会接受到系统提醒。`);
    } else {
console.log(`${this.name}没有添加到货提醒`);
    }
  }
// 到货提醒remindArrival(info) {
console.log(`亲爱的${this.name},您关注的宝贝${info}已到货!`);
  }
}

定义被观察者类

classSubject {
constructor() {
this.observerList= [];
  }
// 订阅subscribe(observer) {
observer.notifyType='add';
this.observerList.push(observer);
  }
// 取消订阅unsubscribe(observerRemove) {
observerRemove.notifyType='cancel';
this.observerList.push(observerRemove);
  }
// 到货提醒notice(good) {
this.observerList.forEach(observer=> {
letobj= {
...good,
...observer,
      };
observer.update(obj);
    });
  }
}

实例化之后的调用

constsubject=newSubject();
constobsA=newObserver('消费者A');
constobsB=newObserver('消费者B');
constobsC=newObserver('消费者C');
// obsA obsB 添加了到货提醒subject.subscribe(obsA);
subject.subscribe(obsB);
// obsC 取消到货提醒subject.unsubscribe(obsC);
// 商品外套已到货constgoodCoat= {
goodName: '外套',
};
// 通知添加到货提醒的消费者subject.notice(goodCoat);

打印输出

亲爱的消费者A,您关注的宝贝外套已到货!

亲爱的消费者B,您关注的宝贝外套已到货!

消费者C取消到货提醒,不会接受到系统提醒。


通过打印的结果可以看出,添加到货提醒的消费者能够收到商品到货通知,取消到货提醒的消费者则不会收到通知。


三、总结

学习下来,我发现实际开发中已经应用了某些设计模式,只是当时并不知道原来这样的功能设计是某个设计模式。

即便原本不擅长的技术,通过不断学习,可以从中找了新的开发思路。

我准备找时间,翻翻自己之前的代码,试试看有没有新的开发思路或者开发方案,即便是之前的代码不能轻易动它,也可以用在下一次的需求中。


心怀热爱,向阳生长


四、参考文章




目录
相关文章
|
15天前
|
前端开发 JavaScript 安全
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第27天】本文介绍了HTTP/2和HTTPS在前端性能调优中的应用。通过多路复用、服务器推送和头部压缩等特性,HTTP/2显著提升了Web性能。同时,HTTPS确保了数据传输的安全性。文章提供了示例代码,展示了如何使用Node.js创建一个HTTP/2服务器。
29 3
|
11天前
|
前端开发 开发者 C++
独家揭秘:前端大牛们如何高效学习新技术,保持竞争力!
【10月更文挑战第31天】前端技术飞速发展,如何高效学习新技术成为关键。本文通过对比普通开发者与大牛们的策略,揭示了高效学习的秘诀:明确目标、主动探索、系统资源、实践应用和持续学习。通过这些方法,大牛们能更好地掌握新技术,保持竞争力。示例代码展示了如何通过实践加深理解。
28 4
|
16天前
|
Rust 前端开发 JavaScript
前端性能革命:WebAssembly在高性能计算中的应用探索
【10月更文挑战第26天】随着Web应用功能的日益复杂,传统JavaScript解释执行模式逐渐成为性能瓶颈。WebAssembly(Wasm)应运而生,作为一种二进制代码格式,支持C/C++、Rust等语言编写的代码在浏览器中高效运行。Wasm不仅提升了应用的执行速度,还具备跨平台兼容性和安全性,显著改善了Web应用的响应速度和用户体验。
31 4
|
15天前
|
前端开发 数据管理 测试技术
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第27天】本文介绍了前端自动化测试中Jest和Cypress的实战应用与最佳实践。Jest适合React应用的单元测试和快照测试,Cypress则擅长端到端测试,模拟用户交互。通过结合使用这两种工具,可以有效提升代码质量和开发效率。最佳实践包括单元测试与集成测试结合、快照测试、并行执行、代码覆盖率分析、测试环境管理和测试数据管理。
31 2
|
16天前
|
前端开发 安全 应用服务中间件
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第26天】随着互联网的快速发展,前端性能调优成为开发者的重要任务。本文探讨了HTTP/2与HTTPS在前端性能优化中的应用,介绍了二进制分帧、多路复用和服务器推送等特性,并通过Nginx配置示例展示了如何启用HTTP/2和HTTPS,以提升Web应用的性能和安全性。
17 3
|
16天前
|
前端开发 JavaScript 数据可视化
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第26天】前端自动化测试在现代软件开发中至关重要,Jest和Cypress分别是单元测试和端到端测试的流行工具。本文通过解答一系列问题,介绍Jest与Cypress的实战应用与最佳实践,帮助开发者提高测试效率和代码质量。
27 2
|
16天前
|
前端开发 JavaScript API
前端框架新探索:Svelte在构建高性能Web应用中的优势
【10月更文挑战第26天】近年来,前端技术飞速发展,Svelte凭借独特的编译时优化和简洁的API设计,成为构建高性能Web应用的优选。本文介绍Svelte的特点和优势,包括编译而非虚拟DOM、组件化开发、状态管理及响应式更新机制,并通过示例代码展示其使用方法。
32 2
|
17天前
|
前端开发 JavaScript 开发者
“揭秘React Hooks的神秘面纱:如何掌握这些改变游戏规则的超能力以打造无敌前端应用”
【10月更文挑战第25天】React Hooks 自 2018 年推出以来,已成为 React 功能组件的重要组成部分。本文全面解析了 React Hooks 的核心概念,包括 `useState` 和 `useEffect` 的使用方法,并提供了最佳实践,如避免过度使用 Hooks、保持 Hooks 调用顺序一致、使用 `useReducer` 管理复杂状态逻辑、自定义 Hooks 封装复用逻辑等,帮助开发者更高效地使用 Hooks,构建健壮且易于维护的 React 应用。
28 2
|
22天前
|
JavaScript 前端开发 测试技术
前端全栈之路Deno篇(五):如何快速创建 WebSocket 服务端应用 + 客户端应用 - 可能是2025最佳的Websocket全栈实时应用框架
本文介绍了如何使用Deno 2.0快速构建WebSocket全栈应用,包括服务端和客户端的创建。通过一个简单的代码示例,展示了Deno在WebSocket实现中的便捷与强大,无需额外依赖,即可轻松搭建具备基本功能的WebSocket应用。Deno 2.0被认为是最佳的WebSocket全栈应用JS运行时,适合全栈开发者学习和使用。
|
18天前
|
前端开发 API UED
深入理解微前端架构:构建灵活、高效的前端应用
【10月更文挑战第23天】微前端架构是一种将前端应用分解为多个小型、独立、可复用的服务的方法。每个服务独立开发和部署,但共同提供一致的用户体验。本文探讨了微前端架构的核心概念、优势及实施方法,包括定义服务边界、建立通信机制、共享UI组件库和版本控制等。通过实际案例和职业心得,帮助读者更好地理解和应用微前端架构。