设计模式 | 青训营笔记

56 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的的第1天

设计模式

image.png

image.png

image.png

image.png

image.png

浏览器中的设计模式

单例模式

定义:全局唯一访问对象
应用场景:缓存,全局状态管理等。eg. Window对象, 框架中的全局状态管理 实现数据缓存

// 使用类实现单例模式
import {api} from './util.js'
export class Request {
    static instance: Request;
    private cache: Record<string, string>;
    
    constructor(){
        this.cache = {};
    }
    
    static getInstance() {
        if (this.instance) {
            return this.distance;
        }
        this.instance = new Request();
        return this.instance;
    }
    
    public async request(url: string){
        if (this.cache[url]){
            return this.cache[url];
        }
        const response = await api(url);
        this.cache[url] = response;
        return response;
    }
    
}
// 使用全局变量实现单例模式
import {api} from './util.js'
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;
}

发布订阅模式

定义:一种订阅机制,可在被订阅对象发生变化时通知订阅者
应用场景:从系统架构之间的解耦,在业务中一些实现模式,像邮件订阅、上线订阅等等

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.followers.push({user, notify});
    }
    
    online() {
        this.status = "online";
        this.followers.forEach(({notify}) => {
            notify(this);
        })
    }
}
image.png

JavaScript中的设计模式

原型模式

定义:复制已有对象来创建新的对象
应用场景:js中对象创建的基本模式
Object.create(prototype, propertiesObject)

image.png image.png
const baseUser: User = {
    name: "",
    status: "offline",
    followers: [],
    subscribe(user, notify){
        user.followers.push({user, notify});
    },
    online(){
        this.status = "online";
        
        this.follower.forEach(({notify}) => {
            notify(this);
        });
    }
}

export const createUser = (name: string) => {
    const user: User = Object.create(baseUser);
    user.name = name;
    user.followers = [];
    return user;
}

代理模式

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

迭代器模式

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

class MyDomElement{
    tag: string;
    children: MyDomElement[];
    constructor(tag: string){
        this.tag = tag;
        this.children = [];
    }
    
    addChildren(component: MyDomElement){
        this.children.push(component);
    }
    
    [Symbol.iterator](){
        const list = [...this.children];
        let node;
        
        return {
            next: () => {
                while((node = list.shift())) {
                    node.children.length > 0 && list.push(...node.children);
                    return {value: node, done: false};
                }
                return {value: null, done: true};
            }
        }
    }
}
test("can iterate root element", () => {
    const body = new MyDomElement("body");
    const header = new MyDomElement("header");
    const main = new MyDomElement("main");
    const banner = new MyDomElement("banner");
    const content = new MyDomElement("content");
    const footer = new MyDomElement("footer");
    
    body.addChildren(header);
    body.addChildren(main);
    body.addChildren(banner);
    body.addChildren(content);
    body.addChildren(footer);
    
    // 此处可以使用for...of...进行遍历!!
    const expectTags: string[] = [];
    for (const element of body) {
        if (element) {
            expectTags.push(element.tag)
        }
    }
})

前端框架中的设计模式

代理模式

组合模式

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