首页 > 其他分享 >day24 设计模式

day24 设计模式

时间:2022-11-07 22:12:43浏览次数:53  
标签:obj log 对象 day24 eventName 事件 console 设计模式

day24 设计模式

概述 :

设计模式是一种解决某个问题的固定模式 ( 原理都是一样的 ) , 它不区分语言 . 常用的设计模式有23种 , 他分为三类 ( 主要针对的是类和对象 )

设计模式的分类

  • 创建型 ( 创建类和对象 , 主要是创建对象 ) 如单例模式 、工厂模式 =>厂家

  • 行为型 ( 主要是对类和对象的方法进行操作 ) 如 观察者模式 =>工人

  • 结构型 ( 将多个小结构变成一个大结构 ) 如组合模式 、代理模式 、 装饰器模式 、 适配器模式 =>搭结构的

 

 

 

设计模式的原则

  • 开闭原则

  • 里氏置换原则

  • 单一原则

  • 依赖倒置原则

  • 接口隔离原则

  • 迪米特原则

工厂模式讲解

  • 根据工厂方法生成对象 ( 生成相关对象 )

function factory(name){
    //手动构建对象
    var obj = new Objcet()
    //给对象进行赋值属性
    obj.name = name
    //手动返回对象
    return obj
}
//调用工厂生产对象
let obj1 = factory('jack')
let obj2 = factory('tom')

单例模式

  • 保证生成的对象的实例 只有一个

闭包实现
//基础类
class Person {
    constructor(){  
    }
}
原型实现
//基础类
class Person {
    constructor(){  
    }
}
//原型的单例
function prototypeSingleton(){
    //判断原型上是否具备newPerson这个属性,没有就赋值,有就直接返回
    if(!prototypeSingleton.prototype.newPerson){
        prototypeSingleton.prototype.newPerson = new Person()
    }
    return prototypeSingleton.prototype.newPerson
}
let person3 = prototypeSingleton()
let person4 = prototypeSingleton()
console.log(person3 == person4)
静态属性实现
//基础类
class Person {
    constructor(){  
    }
}
//静态属性的单例
function staticSingleton(){
    //判断静态属性上是否具备newPerson这个属性,没有就赋值,有就直接返回
    if(!staticSingleton.newPerson){
        staticSingleton.newPerson = new Person()
    }
    return staticSingleton.newPerson
}
let person5 = staticSingleton()
let person6 = staticSingleton()
console.log(person5 == person6)
全局属性实现
  • window是浏览器的global对象 , 但是其他的global对象 有可能不是window

//基础类
class Person {
    constructor(){  
    }
}
//全局对象实现
function globalSingleton(){
    if(!window.newPerson){
        window.newPerson = new Person()
    }
    return window.newPerson
}
let person7 = staticSingleton()
let person8 = staticSingleton()
console.log(person7 == person8)

组合模式 (*)

  • 将多个对象的相同方法和属性组合到一块 ( 将不同的方法组合在一块执行 )

基础内容

class GoToHome{
    constructor(){
        this.action=()=>{
            console.log('回家')
        }
    }
}
class OpenComputer{
    constructor(){
        this.action=()=>{
            console.log('打开电脑')
        }
    }
}
class PlayGame{
    constructor(){
        this.action=()=>{
            console.log('玩游戏')
        }
    }
}
new GoToHome().action()
new OpenComputer().action()
new PlayGame().action()

将多个方法组合在一块 , 统一调用

class Combiner{
    constructor(){
        this.list = []
    }
    //加入,把对应的对象添加到list中
    push(obj){
        this.list.push(obj)
    }
    //执行 ,执行函数,可传多个参数
    excute(fnName,...arg){
        //遍历数组
        this.list.forEach((item)=>{
            //执行对应的函数并传参
            item[fnName]() // item[fnName].call(this,..arg)
        })
    }
}
let combiner = new Combiner()
//将对象加入
combiner.push(new GoToHome())
combiner.push(new OpenComputer())
combiner.push(new PlayGame())
//执行action方法
combiner.excute('action')
组合模式在vue中的使用
  • Vue.use (自动执行install)

  • install 方法

  • 如果在use里面传入的是一个函数,那么它会把这个函数直接当成install,如果传的是对象,它会自动去找里面的install方法

模拟实现use和install
class Vue{
    constructor(){
        this.fnList=[]
    }
    use(obj){
        //如果obj是一个函数,那么就把这个函数直接当成install执行
        if(typeof obj =='function'){
            this.fnList.push(obj)
        } 
        //如果obj是一个对象,那就去对象内找install方法
        if(typeof obj=='object'){
            this.fnList.push(obj.install)
        }
        //调用执行方法
        this.excute()
    }
    excute(){
        //遍历对应的函数列表并执行
        this.fnList.forEach((fn)=>{
            fn()
        })
    }
}
let vue = new Vue()
//调用use方法
vue.use(()=>{
    console.log('hello')
})
vue.use({
    install(){
        console.log('world')
    }
})

装饰器模式 (又叫做包装模式)

场景:

我现在有三个车的类 , 这三个车都有对应的跑的方法 , 现在我先给这三个车添加一个飞的方法 ( 设计模式开闭原则 , 一个类一旦写完了不允许内部再进行修改 ),这个时候就可以使用装饰器模式

概述 :

装饰器模式是在不影响原本类的基础上,进行功能扩展,它又叫做包装模式

实现
基础类
class Car{
    constructor(){
        run(){
            console.log('跑')
        }
    }
}
包装类
class Decorator{
    constructor(car){
        //将基础类传入包装类
        this.car=car
    }
    fly(){
        console.log('飞')
        this.car.run()
    }
}
new Decorator(new Car()).fly()
在typeScript中有个对应的装饰器修饰 @Decorator

观察者模式 (*)

概述 :

观察者模式是前端最常用的模式,它又被称为发布者-订阅者模式。它的核心是一个发布者,它有自己的订阅者,当发布者发布信息时,订阅者会收到信息然后可以进行处理。

观察者模式的核心内容
  • 发布者

  • 订阅者

  • 相关处理

其实我们的事件就是一个观察者模式(事件发布者,事件监听者,事件处理)
element.addEventListener('事件名',处理函数)
element.removeEventListener('事件名',处理函数)
简单的事件示例
<button>点我</button>
<script>
    let btn = document.querySelector('button')
    btn.addEventListener('click',handler)
    function handler(){
        console.log('点击了')
    }
</script>
  • 发布者 button

  • 订阅者 javaScript引擎

  • 处理 handler

分析事件的相关内容
  • 元素 ( 发布者 )

  • 事件名

  • 处理函数

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

  • 发布者和事件名的关系也是一对多,就是一个发布者可以发布多个事件

根据事件监听机制来模拟观察者
事件监听的过程
  • 事件发布 (有对应的事件名)on

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

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

代码构建
class ObServer{
    constructor(){
        //{click:[handler1,handler2],mouseenter:[handler1,handler2]}
        this.obj = {}
    }
    //事件发布 事件名,处理函数
    on(eventName,handler){
        
    } 
    //事件执行 事件名,参数
    emit(eventName,...arg){
        
    }
    //事件取消 事件名,处理函数
    off(eventName,handler){     
    }
}
代码完善
on方法
class ObServer{
    constructor(){
        this.obj = {}
    }
    //事件发布 事件名,处理函数
    on(eventName,handler){
        //判断是否有事件,没有就先赋值一个空数值
        if(!this.obj[eventName]){
            this.obj[eventName]=[]
        }
        //再将事件添加进去
        this.obj[eventName].push(handler)
    }
    //事件执行 事件名,参数
    emit(eventName,...arg){
        
    }
    //事件取消 事件名,处理函数
    off(eventName,handler){
        
    }
}
emit方法
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((item)=>{
            item.call(this,...arg) //item()
        })
    }
    //事件取消 事件名,处理函数
    off(eventName,handler){
        
    }
}
let obServer = new ObServer()
obServer.on('click',(params1,params2)=>{
    console.log(111+params1+params2)
})
obServer.emit('click','10','hi')//121hi
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((item)=>{
            item.call(this,...arg)
        })
    }
    //事件取消 事件名,处理函数
    off(eventName,handler){
        //判断是否有事件,没有就直接返回
        if(!this.obj[event]) return 
        //遍历它的处理函数
        this.obj[eventName].forEach((item,index)=>{
            //如果函数一致就根据下标删除事件
            if(Object.is(item,handler)){
                this.obj[eventName].splice(index,1)
            }
        })
    }
}
let obServer = new ObServer()
obServer.on('click',(params1,params2)=>{
    console.log(111+params1+params2)
})
function fn(){
    console.log('aloha')
}
obServer.on('dbclick',fn)
obServer.off('dbclick',fn)//删除
obServer.emit('dbclick')//undefined
obServer.emit('click','10','hi')//121hi
注意事项
  • emit执行 , 他可以传参传给对应的on方法里面的处理函数 ( vue中父传子的实现 及bus传值的实现 )

  • off调用一定要在emit执行之前

  • 观察者模式是vue2底层实现

代理模式(*)

概述 :

在不改变原本的类的基础上 , 对于对象进行功能加强 , 代理模式代理出来的是对象 , 代理模式低耦合

示例 :

你家里需要装修 , 但是你不想动手 , 这个时候你就会找一个装修队代替你装修

代理对象和本身被代理对象是两个不同的对象 , 但是实际操作的内容是同一个 ,

核心关键词
  • 代理对象 --装修队

  • 被代理对象 --我

  • 操作内容 --房子

代理的实现

在js中 , es7新增了一个Proxy的类 , 这个类是专门来做代理的 , 所以我们只需要掌握这个类的使用就可以了~

Proxy的使用

新建代理对象 (通过proxy的构造)

let proxy = new Proxy(被处理对象,相关的处理对象)
基础使用
//被代理对象
let obj = {
    name:'jack',
    age:18
}
//通过Proxy来新建代理对象
//Proxy的构造函数需要传入被代理对象 以及相关的处理对象
let proxy = new Proxy(obj,{
    //get是在获取的时候调用,它返回的结果就是你接收的结果
    //目标对象(被代理对象),属性(实际访问的属性),代理对象(当前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是设置的时候调用
    //目标对象(被代理对象),属性(实际访问的属性),属性值,代理对象(当前proxy)
    set(target,attribute,value,proxyObj){
        console.log('调用了set')
        target[attribute] = value
    },
    //definedProperty是定义属性,也就是赋值新的属性
    //目标对象(被代理对象),属性(实际访问的属性),属性的详情信息
    defineProperty(target,attribute,descriptor){
        console.log('定义了新的属性')
        console.log(descriptor)
    },
    //deleteProperty是删除属性的时候调用
    //目标对象(被代理对象),属性(实际访问的属性),代理对象(当前proxy)
    deleteProperty(target,attribute,proxyObj){
        console.log('删除属性')
        delete target[attribute]
    }
})
console.log(proxy.name)//调用了get,姓名为jack
console.log(proxy.age)//调用了get,18岁
proxy.name = 'rose'    //调用了set
Object.defineProperty(proxy,'sex',{
    configurable:true,//是否可以删除
    encmerable:true,//是否可以遍历
    value:'男',
    writable:true//是否可以修改
})
delete proxy.name//删除属性
proxy的处理对象的四大属性
  • get 访问属性的时候调用

console.log(proxy.name) //调用了get
console.log(proxy.age)  //调用了get
  • set 设置属性的时候调用

proxy.name = '你好' //调用set
  • defineProperty 定义属性的时候调用

Objtect.defineProperty(proxy,'sex',{
    configurable:true, //是否可以删除
    enumerable:true,   //是否可以遍历
    value:'男',          //属性值
    writable:true       //是否可以改变
})
deleteProperty 删除属性的时候调用

delete proxy.name //调用deleteProperty

总结

  • Proxy 是ES7新增的一个类 , 它返回的是一个对象

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

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

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

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

  • Proxy是vue3的底层实现之一

适配器模式

概述 :

将旧的内容进行新的适配 , 在原本的基础上做兼容处理

常用的业务场景 :
  • 旧的接口替换成新的接口 ( 在不改变原本内容的情况下完成替换 )

  • 表单验证 ( 根据场景来切换相关的验证 )

示例:
  • 家庭用电最大功率为22v

  • 接入的电压220v

  • 中间就需要继电器 ( 适配口 )

代码实现
class Phone{
    constructor(){  
    }
    fn(){
        return 22
    }
}
class Adaptive{
    constructor(){
    }
    fn(){
        return '220转为'+new Phone().fn()
    }
}
//实际使用的是对应的适配的内容
console.log(new Adaptive().fn())

标签:obj,log,对象,day24,eventName,事件,console,设计模式
From: https://www.cnblogs.com/itlulu/p/16867662.html

相关文章

  • JAVA 模板设计模式
    今天来介绍下一个我觉得蛮不错的设计模式(比较容易应用于业务场景),它就是---模板设计模式。OK,我们直接看代码:模板模式,那当然我们需要建一个模板先,建一个抽象类,VehicleControlM......
  • 23 种设计模式C++实现
    设计模式的分类总体来说设计模式分为三大类:创建型模式,共五种:​​单例模式​​、​​原型模式​​、​​工厂方法模式​​、​​抽象工厂模式​​、​​建造者模式​​。结构......
  • 设计模式(十八)桥接模式 C++
    桥接模式即将抽象部分与它的实现部分分离开来,使他们都可以独立变化。桥接模式将继承关系转化成关联关系,它降低了类与类之间的耦合度,减少了系统中类的数量,也减少了代码量。桥......
  • JAVA 责任链设计模式
    这次介绍责任链模式,采用最普遍的请假例子来编码实现。先给列出个模拟的需求,一个人请假,调用一个接口,传入的参数是他请假的天数。然后,请假的天数---->如果小于2天,由直属领导......
  • 创建型设计模式-原型模式(深拷贝,浅拷贝)
    Person类:publicclassPerson{publicstringName{get;set;}publicintAge{get;set;}publicAddressAddress{get;set;......
  • 创建型设计模式-单例模式(为什么要双重加锁判断)
    代码publicclassSingleObject{privatestaticSingleObjectinstance;privatestaticobjectlockobj=newobject();privateSingleObject(){}publicstatic......
  • 设计模式学习(二):单例模式
    设计模式学习(二):单例模式作者:Grey原文地址:博客园:设计模式学习(二):单例模式CSDN:设计模式学习(二):单例模式单例模式单例模式是创建型模式。单例的定义:“一个类只允许创建......
  • 〖JAVA养成计划〗设计模式-单例设计模式以及衍生的多例设计模式
     单例设计模式packagecom.tongbu;/***单例设计模式分为两类:*①是俄汉式*②是懒汉式*以下程序是俄汉式:不管程序中有没有使用,都实例化对象。*@authorAdministrat......
  • 23种设计模式之自定义Spring框架(五)
    7,自定义Spring框架7.1spring使用回顾自定义spring框架前,先回顾一下spring框架的使用,从而分析spring的核心,并对核心功能进行模拟。数据访问层。定义UserDao接口及其子......
  • 23种设计模式之设计模式介绍(一)
    1,设计模式概述1.1软件设计模式的产生背景"设计模式"最初并不是出现在软件设计中,而是被用于建筑领域的设计中。1977年美国著名建筑大师、加利福尼亚大学伯克利分校环境......