前端设计模式应用 | 青训营笔记

45 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的的第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;
}

image.png

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);
        });
    }
}

测试函数: image.png

JavaScript中的设计模式

1、原型模式

定义:复制已有对象来创建新的对象。
应用场景:JS种对象创建的基本模式。

用原型模式创建上线订阅中的用户

image.png 测试: image.png

2、代理模式

定义:可自定义控制对原对象的访问方式。并且允许在更新前后做一些额外处理。
应用场景:监控、代理工具、前端框架实现等。

通过代理模式实现用户状态订阅

image.png image.png

3、迭代器模式

定义:在不暴露数据类型的情况下访问集合中的数据。
应用场景:数据结构中有多种数据类型,列表、树等提供通用操作接口。

用for of 迭代所有组件

image.png 测试:
image.png

前端框架中的设计模式

1、代理模式

与之前的代理模式有一些区别。

vue组件实现计数器

image.png

前端框架中对DOM操作的代理

image.png

2、组合模式

定义:可多个对象组合使用,也可单个对象独立使用。
应用场景:DOM、前端组件、文件目录、部门。

总结

1、总结出抽象的设计模式相对比较简单,但是想要将抽象的设计模式套用到场景中却十分困难。
2、现代编程语言的多编程范式带来的更多可能性。
3、真正优秀的开源项目学习设计模式并不断实践。