web前端-所谓的八种设计模式

本文介绍了单例模式、简单工厂模式、策略模式、适配器模式、装饰器模式、代理模式以及观察者模式的基本概念和在实际代码中的应用示例,展示了如何利用这些模式提高代码的灵活性和可维护性。
摘要由CSDN通过智能技术生成

设计模式的根本:找到代码当中的变与不变,把它分离开来,使得变的部分更加的灵活,不变的部分更加稳定。

单例模式

说明:定义一个类,生成一个实例,而且整个项目仅此一个实例;

// 实践案例说明 axios的使用 axios就属于一种单例模式
// 比如封装axios做我们的请求
utils/request.ts
// 定义一个类
class HttpRequest {
    instance:AxiosInstance;
    constructor(options:CreateAxiosOptions){
        this.instance = axios.create(options)
    }
    
    setHeader(){...}
    get(){...}
    post(){...}
    put(){...}
    delete(){...}
}
// 生成一个实例
const request = new HttpRequest({});
// 全局仅用这么一个请求实例
export default request;

// 使用当前的请求实例
import request '@/utils/request';
const fetchData = (url)=>{
   return request.get(url)

简单 工厂模式

目的是:更方便去创建实例,而且每个实例都是独立并全新的;  

// 实践案例 axios.create()  目的:每次使用这个方法的时候都是返回一个全新的实例;
// 原理部分
class Axios {};
class A {
    create(){
        return new Axios();
    }
}
const axios = new A();
export default axios; // 导出

// 如何使用
import axios from 'axios';
// 创建很多实例,他们都是各自独立的
const httpRequest1 = axios.create();
const httpRequest2 = axios.create();
const httpRequest3 = axios.create();

策略模式

说明:依据不同的策略去做不同的事情;比如存在很多if else这种代码的情况;

// 比如需要依据不同的年龄端去做不同的处理
// 以下的坏处:可读性很差、可维护性差、可拓展性差;
const doSomething = (age:number) =>[
    if (age === 20){
        // doSomething
    }else if (age === 30){
        // doSomething
    }else if (age ===40) {
        // doSomething
    }else{
        // doSomething
    }

// 通过map存储,好拓展
const doMap : Record<number,Function> = {
    20:()=>{},
    30:()=>{},
    40:()=>{},
    50:()=>{},
}
const doSomething = (age:numbner)=>[
    doMap[age]?.()

适配器模式

说明:数据需要做格式转化、格式统一的时候;  

// 比如一一个场景,后端返回了三种数据格式,前端需要把这三种格式转换界面所需要的格式;
const data1 = [{age1:10,name1:'汪子'}];
const data2 = [{age2:20,name2:'jessica'}];
const data3 = [{age3:40,name3:'小明'}];

// 依据三种不同的格式,写出3个类去进行适配,所谓的适配类
class Adapter1 {
    data: { age1: number ,name:string}
constructor(data){
    this.data = data
}
transform(){
    return this.data.map(
        ({age1,name1})=>({
        age:age1,
        name:name1
        })
      )
}
}
class Adapter2 {...} // 同上
class Adapter2 {...} // 同上

// 当需要转换数据的时候,调用这些类就好了
const adapter1 = new Adaper1(传入data);
const newData = adapter1.transform();

装饰器模式

说明:定义一个类,在不改变这个类的前提下,去拓展这个类的功能;其实相当于创建新的类;  

这里需要仔细与“继承”做好区分,研究的时候也困惑过,建议自行了解清楚

// 比如以下实践
// 我先定义一个不同的类别 人类
class Person {
    say(){
        alert('我是一个人类')
    }
}

// 我需要在这个普通人类拓展一个身份,老师
class Teacher{
    person:Person
    consturctor(person){
        this.person = person
    }
    say(){
        this.person.say();
        alert('我也是一个老师')
    }
}

const p1 = new Person();  p1.say() ; // 我是一个人类
const t1 = new Teacher(p1) ; t1.say() // 我是一个人类 我也是一个老师

代理模式

说明:为我们的对象提供一个代理,以便控制对这个对象的访问,不能直接访问目标对象;

// 最好的实践案例就是ES6里面的Proxy,它就是最好的代理模式案例
const handler = {
    get:function(obj,prop){
        return prop in obj ? obj[prop] :7;
    }      x
}
const p = new Proxy({},handler);
p.a = 1;
p.b = undefined;
console.log(p.a,p.b) // 1 undefined
console.log('c' in p,p.c) // false 7 

观察者模式

说明:(相互依赖)定义对象之间的一对多的依赖关系,当一个对象状态发生改变时,依赖它的其他对象都会得到通知;  

观察者模式的发布和订阅时相互依赖的;  

// 定义被观察者
class Dep {
    status : string
    observers: any[]
    constructor(observer){
        this.status = '不开心';
        this.observers = [];
    }
    // 获得subject的状态
    get(){  }
    // 重新设置subject的状态
    set(status){
        this.status = status;
        this.notify();
    }
    // subject状态更新,需要通知到所有观察者并调用其更新方法
    notify(){
        this.observer.forEach(item=>{item.update(this)})
    }
    push(observer){
        this.observers.push(observer);
    }
}

// 定义观察者
class Observer {
    name:string
    constructor(name,subject){
        this.name = name;
        this.subject.push(this);
    }
    update(subject){
        console.log(`${subject.status}发生变化了,${this.name}观察了`)
    }
}

const dep = new Dep();
const observer1 = new Observer('观察者1',dep);
const observer2 = new Observer('观察者2',dep);

// 如何进行
subject.set('开心')

发布订阅模式

说明:发布订阅模式时不相互依赖的,因为有一个统一调度中心;  

// Vue 的EventBus就是发布订阅模式

        class EventBus {
            callbackId
            callbackList
            constructor(){
            this.callbackId = 0;
            this.callbackList = {};
            }
            // 订阅 并返回删除的事件
            on(name,fn){
                if(!this.callbackList[name]){ this.callbackList[name] = [];}
                if(this.callbackList[name]){ this.callbackId++;}
                this.callbackList[name][this.callbackId] = fn
                const off = ()=>{
                    delete this.callbackList[name][this.callbackId];
                    if(Object.keys(this.callbackList[name].lenght) == 0){ delete this.callbackList[name]}
                }
                return {off}
            }
            // 发布
            emit(name,arg){
                if(this.callbackList[name]){
                for(let id in this.callbackList[name]){
                    this.callbackList[name][id](arg)
                }
                }else{
                    console.log(this.callbackList[name] + 'not found')
                }
            }
            // 仅仅订阅一次就不再接受信息
            once(name,fn){
                const onceFn = (arg)=>{
                   if(fn){ fn(arg); } 
                    fn = null
                }
                this.on(name,onceFn);
            }
        }

        const event = new EventBus();
        event.on('hyy',(arg)=>{
        console.log('hyy订阅了' + arg)});
        event.emit('hyy','哈哈')

        event.once('oncetime',(arg)=>{
        console.log('一次订阅了' + arg)});
        event.emit('oncetime','哈哈')
        event.emit('oncetime','呜呜')

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值