部分设计模式

设计模式

概述:

设计模式是一种固定的解决某个问题的一种方式,他是一个固定的模式,不区分语言.常用的设计模式有23种,它分为三类

设计模式的分类
  • 创建型 (创建对象) 单例模式 工厂模式
  • 结构型(将多个小结构变成一个大结果) 组合
  • 行为型(对应类和对象的行为进行相关处理)

设计模式的原则

  • 开闭原则:软件对象(类,模块,方法)对于扩展是开放的,对于修改是关闭的

  • 里氏置换原则:子类应当可以替换父类出现在父类能够出现的地方

  • 单一原则:一个对象不应该承担太多功能

  • 依赖倒置原则

  • 接口隔离原则

  • 迪米特原则

工厂模式讲解

原理:根据对应的工厂方法生成对应的对象

  // 封装一个函数来创建对象---工厂函数
  function createObj(name, age, gender) {
    // 1. 创建空对象
    let obj = new Object()
    // 2. 给对象添加成员
    obj.name = name;
    obj.age = age;
    obj.gender = gender;
    // 3. 返回创建的对象
    return obj;
  }
	//4.调用工厂生成对象
  let p1 = createObj('zs', 17, '男')
  let p2 = createObj('ls', 18, '男')
  let p3 = createObj('ww', 19, '女')

单例模式

原理:通过限制类的实例化次数,让一个类只有一个实例对象

单例模式的四种实现方式
基础类
 class Person{
            constructor(){

            }
        }

闭包

 function danli() {
            var newDan = null
            return function () {
                if (!newDan) {
                    newDan = new Person()
                }
                return newDan
            }
        }
        let single = danli()
        let person1 = single()
        let person2 = single()
        console.log(person1 == person2);//true
静态属性案例
 function staticSingleton(){
            if(!staticSingleton.newPerson){
                staticSingleton.newPerson=new Person()
            }
            return staticSingleton.newPerson
        }
        let person3=staticSingleton()
        let person4=staticSingleton()
        console.log(person3 == person4);  //true
全局实现(window是浏览器的全局对象 ,但是其他的全局对象不一定是window)
        function windowSingleton(){
            if(!window.instance){
                window.instance=new Person()
            }
            return window.instance
        }
        let person5=windowSingleton()
        let person6=windowSingleton()
        console.log(person5 == person6);  //true
原型实现
  function prototypeSingleton() {
            //判断原型上是否具备newPerson这个属性
            if (!prototypeSingleton.prototype.instance) {
                prototypeSingleton.prototype.instance = new Person()
            }
            return prototypeSingleton.prototype.instance
        }
        let person3 = prototypeSingleton()
        let person4 = prototypeSingleton()
        console.log(person3 == person4)//true

组合模式

原理:将多个对象的相同方法或者属性组合到一块(将不同的方法组合在一起执行)

        class GoToHome{
            constructor(){
                this.action=()=>{
                    console.log('回家');
                }
            }
        }
        class OpenComputer{
            constructor(){
                this.action=()=>{
                    console.log('打开电脑');
                }
            }
        }
        class PlayGame{
            constructor(){
                this.action=()=>{
                    console.log('玩游戏');
                }
            }
        }
        class Combiner{
            constructor(){
                this.list=[]
            }
            push(obj){
                this.list.push(obj)
            }
            execute(fnName,...arg){
                this.list.forEach(item=>{
                    item[fnName].call(this,...arg)
                })
            }
        }
        let combiner=new Combiner()
        combiner.push(new GoToHome())
        combiner.push(new OpenComputer())
        combiner.push(new PlayGame())
        combiner.execute('action')

装饰器模式

原理:扩展的是对象的功能,而无需修改现有的类或者是构造函数

        //基础类
        class Car {
            constructor() {

            }
            run() {
                console.log('跑');
            }
        }
        class Fly {
            constructor(car) {
                this.car = car
            }
            fly() {
                console.log('飞');
                this.car.run()
            }
        }
        class Sw {
            constructor(fly) {
                this.fly = fly
            }
            sw() {
                console.log('游');
                this.fly.fly()
            }
        }
        new Sw(new Fly(new Car())).sw()//在跑的前提下加入了飞和游

观察者模式(发布者-订阅者模式)

原理:一个对应的发布者进行发布,就会有一个对应的订阅者(对发布的内容进行监听),发布者将对应的内容发布,订阅者就会收到信息从而进行对应的处理

核心
  • 发布者
  • 订阅者
  • 相关处理

事件就是一个观察者模式

简单的事件案例(在事件当中订阅者一般都是JavaScript引擎)

    let btn = document.querySelector('button')
    btn.addEventListener('click', handler)

    function handler() {
        console.log('我点击了');
    }
    //发布者 button
    //订阅者 JavaScript引擎
    //处理 handler
相关关系

事件名和处理函数的关系 一对多(一个事件可以有多个处理函数) click:[handler1,handler2]

发布者和事件名的关系 一对多(一个发布者可以发布多个事件) {事件名;[处理函数]}

事件监听的过程

事件发布(对应的事件名)+on

事件执行(根据对应的事件名执行相关的处理函数)+emit

事件取消(将对应的事件移出) off

        class obServer {
            constructor() {
                    this.obj = {}
                }
                //事件发布 事件名 处理函数
            on(eventName, handler) {
                    //判断当前事件名是否存在,不存在就给一个空数组
                    if (!this.obj[eventName]) {
                        this.obj[eventName] = []
                    }
                    //将事件添加进去  将处理函数添加到这个事件中
                    this.obj[eventName].push(handler)
                }
                //发布事件  (...用于定义多个形参(不限制形参的个数))
            emit(eventName, ...arg) {
                    //判断事件名是否存在
                    if (!this.obj[eventName]) return
                        //获取这个事件里面所有的处理函数,去执行这些处理函数
                        //遍历对应的处理函数数组
                    this.obj[eventName].forEach(handler => {
                        handler.call(this, ...arg)
                    })
                }
                //事件取消
            off(eventName, handler) {
                if (!this.obj[eventName]) return //如果这个事件名不存在就停止继续
                    //遍历对应的事件名里面的处理函数数组 找到匹配的handler函数将他删除
                this.obj[eventName].forEach((v, i) => {
                    if (Object.is(v, handler)) {
                        this.obj[eventName].splice(i, 1)
                    }
                })
            }
        }
        //事件执行 事件名 传入的参数


        let observer = new obServer()
        function handler(){
console.log('监听了')}
observer.on('abc',handler)
        observer.on('load', (a1, a2) => {
            console.log('监听了' + a1 + a2);
        })
  obServer.off('abc', handler)
        observer.emit('load', 10, '你好')

emit执行可以传参个给对应的on方法里面的处理函数

off调用一定要在emit之前

代理模式

原理:在不改变原本类的基础上,对于对象进行功能增强,代理模式代理出来的是对象.

//被代理对象
        let obj = {
            name: 'jack',
            age: 18
        }
        //通过proxy来新建代理对象 
        //Proxy的构造函数需要传入被代理对象 以及相关的处理对象
        //对于handler他是对于所有的属性进行操作
        //get在获取属性的时候调用  他返回的结果就是你接收的结果
        //set对于设置属性的时候调用
        let proxy = new Proxy(obj, {
            //目标对象(被代理对象) 属性(实际访问的属性)  代理对象(当前proxy)
            get(target, attribute, proxyObj) { //这个里面返回的值就是当前的获取值
                console.log('调用了get');
                if (attribute == 'name') {
                    return '姓名为' + target[attribute]
                } else if (attribute == 'age') {
                    return target[attribute] + '岁'
                }
                return target[attribute]
            },
            //目标对象(被代理对象) 属性(实际访问的属性)值 代理对象(当前proxy)
            set(target, attribute, value, proxyObj) {
                console.log('调用了set');
                target[attribute] = value
            },
            //定义属性 赋值新的属性  目标对象  属性名  属性的详情信息
            defineProperty(target, attribute, descriptor) {
                console.log('新的属性定义');
                console.log(descriptor);
                // Object.defineProperty(target,attribute,descriptor)
            },
            //删除属性 delete的时候
            deleteProperty(target, attribute, proxyObj) {
                console.log('删除属性');
                delete target[attribute]
            }
        })
        console.log(proxy.name);
        console.log(proxy.age);
        proxy.name = '你好'
        console.log(proxy.name);
        delete proxy.name
        console.log(proxy.name);
        Object.defineProperty(proxy, 'sex', {
            configurable: true, //是否可以删除
            enumerable: true, //是否可以遍历
            value: '男', //属性值
            writable: true //是否可以改变
        })
        console.log(proxy);
简单举例
 /* 
    代理设计模式:
      - 使用代理对象来完成 对象的操作        
  */
  // 王同学 家的大门需要人看--- 使用代理模式

  // 人类 
  class Person {
    // 人名字和代理对象
    constructor(name, delegate) {
      this.name = name;
      this.delegate = delegate;
    }
    lookDoor() {
      // 让代理对象看大门
      this.delegate.lookDoor();
    }
  }

  // 看门小狗 --- 具备看门的能力
  class Dog {
    constructor(name) {
      this.name = name;
    }
    lookDoor() {  
      console.log(`${this.name}正在聚精会神的看着大门`)
    }
  }

  let wc = new Dog('旺财');
  // 王同学 需要一个看大门的
  let w = new Person('王同学', wc);
  w.lookDoor()

  // 看门老虎 --- 具备看门的能力
  class Tiger {
    constructor(name) {
      this.name = name;
    }
    lookDoor() {
      console.log(`${this.name}正在虎视眈眈的看着大门`)
    }
  }

  // 旺财 和小花走了
  w.delegate = new Tiger('小黄');
  w.lookDoor()

proxy(vue3的底层实现之一)

        let obj = {
            name: 'jack',
            age: 18
        }
        let proxy = new Proxy(obj, {
            //目标对象(被代理对象) 属性(实际访问的属性)  值  代理对象(当前的proxy)
            get(target, attribute, proxyObj) {
                console.log('调用了get');
                if (attribute == 'name') {
                    return '姓名为' + target[attribute]
                } else if (attribute == 'age') {
                    return target[attribute] + '岁'
                }
                return target[attribute]
            },
            set(target, attribute, value, proxyObj) {
                console.log('调用了个set');
                target[attribute] = value
            },
            //定义属性 赋值新的属性   目标对象 属性名  属性的详细信息
            defineProperty(target, attribute, descriptor) {
                console.log('新的属性定义');
                console.log(descriptor);
                //Object.defineProperty(target,attribute,descriptor)
            },
            deleteProperty(target, attribute, proxyObj) {
                console.log('删除属性');
                delete target[attribute]
            }
        })
        proxy.name = '你好'
        console.log(proxy.name);
        console.log(proxy.age);
        // Object.defineProperties(proxy, 'sex', {
        //     configurable: true,
        //     enumerable: true,
        //     value: '男',
        //     writable: true
        // })
        console.log(proxy);
  • Proxy是一个es7新增的一个类 他返回的是一个对象

  • Proxy里面传入被代理对象和对应的处理对象

  • 处理对象包含4个方法(get set defineProperty deleteProperty)

  • Proxy里面实际操作是被代理对象 (如果在里面操作代理对象会造成栈溢出)

  • 代理对象和被代理对象不是一个对象 但是操作的内容是一个都是被代理对象

  • Proxy是vue3的底层实现之一
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值