这是我参与「第四届青训营 」笔记创作活动的的第6天,今天的课程是「前端设计模式应用」,老师主要讲解了 什么是设计模式 、 23种设计模式 、 设计模式分类 、 浏览器中的设计模式 、 JavaScript中的设计模式 、 前端框架中的设计模式等内容。
什么是设计模式
设计模式是软件设计中常见问题的解决方案模型。
23种设计模式
设计模式分类
- 创建型:如何创建一个对象
- 结构型:如何灵活地将对象组装成较大的结构
- 行为型:负责对象间的高效通信和职责划分
浏览器中的设计模式
1、单例模式
定义:全局唯一访问对象,即任意一个地方访问的都是同一个对象,而在任意一个地方对这个对象进行修改都会反映到这个对象上。
应用场景:缓存、全局状态管理等。
用单例模式实现请求缓存
import { api } from "./utils";
export class Requset{
static instance:Requset;
private cache:Record<string,string>;
constructor(){
this.cache = {};
}
//如果instance存在则返回自身,否则创建一个新的并返回
static getInstance(){
if(this.instance){
return this.instance;
}
this.instance = new Request();
return this.instance;
}
//真正缓存的实现,如果缓存池中有url的内容就返回缓存中的,否则就调用api并把它写入缓存池中
public async request(url:string){
if(this.cache[url]){
return this.cache[url];
}
const response = await api(url);
this.cache[url] = response;
return response;
}
}
关于这个单例的使用:
//没有缓存的场景
test("should response more than 500ms with class", async()=>{
const request = Requset.getInstance();
const startTime = Date.now();
await request.request("/user/1");
const endTime = Date.now();
const costTime = endTime - startTime;
expect(costTime).toBeGreaterThanOrEqual(500);
});
//有缓存的场景
test("should response quickly second time with class", async()=>{
const request1 = Requset.getInstance();
await request1.request("/user/1");
const startTime = Date.now();
const request2 = Requset.getInstance();
await request2.request("/user/1");
const endTime = Date.now();
const costTime = endTime - startTime;
expect(costTime).toBeLessThan(50);
});
更简单、更易使用的版本:
import { api } from "./utils";
const cache:Record<string,string> = {};//定义空缓存
export const request = async(url:string){
if(cache[url]){
return cache[url];
}
const response = await api(url);
cache[url] = response;
return response;
}
2、发布订阅模式
定义:一种订阅机制,可在被订阅对象发生变化时通知订阅者。
应用场景:从系统架构之间的解耦,到业务中的一些实现模式,像邮件订阅、上线订阅等。
用发布订阅模式实现用户上线订阅
type Notify = (user:User) => void;
export class User{
name:string;
status:"offline" | "online";
followers:{user:User;notify:Notify}[];
constructor(name:string){
this.name = name;
this.status = offline;
this.followers = {};
}
subscribe(user:User,notify:Notify){
user.folloewers.push({user,notify});
}
online(){
this.status = "online";
this.followers.forEach(({notify})=>{
notify(this);
});
}
}
测试函数:
JavaScript中的设计模式
1、原型模式
定义:复制已有对象来创建新的对象。
应用场景:JS种对象创建的基本模式。
用原型模式创建上线订阅中的用户
测试:
2、代理模式
定义:可自定义控制对原对象的访问方式。并且允许在更新前后做一些额外处理。
应用场景:监控、代理工具、前端框架实现等。
通过代理模式实现用户状态订阅
3、迭代器模式
定义:在不暴露数据类型的情况下访问集合中的数据。
应用场景:数据结构中有多种数据类型,列表、树等提供通用操作接口。
用for of 迭代所有组件
测试:
前端框架中的设计模式
1、代理模式
与之前的代理模式有一些区别。
vue组件实现计数器
前端框架中对DOM操作的代理
2、组合模式
定义:可多个对象组合使用,也可单个对象独立使用。
应用场景:DOM、前端组件、文件目录、部门。
总结
1、总结出抽象的设计模式相对比较简单,但是想要将抽象的设计模式套用到场景中却十分困难。
2、现代编程语言的多编程范式带来的更多可能性。
3、真正优秀的开源项目学习设计模式并不断实践。