【学习笔记73】设计模式

news/2024/7/8 4:11:33

一、认识单利模式(设计模式)

  • 设计模式:为了 实现某一类功能的一个简洁优化的写法

(一)单利模式

  • 一个构造函数(类), 一生只能有一个实例化对象

(二)案例需求

  • 一个构造函数, 在实例化对象时, 判断是否为第一次实例化
  • 第一次创建一个实例化对象, 然后返回
  • 不是第一次想办法拿到第一次的实例化对象, 然后返回

(三)解决方法

  • 拿一个变量, 初始值给一个null
  • 在实例化对象时, 第一次实例化, 直接将实例化赋值给变量, 然后将变量返回
  • 后续再实例化的时候, 直接返回刚才的变量

(四)核心代码 

        class Dialog {
            constructor(title) {
                console.log('创建一个弹出框插入到页面中, 类型为: ')
                this.title = title
            }
        }

        let instance = null
        function newDialog(type) {

            if (instance === null) {
                instance = new Dialog(type)
            }

            return instance
        }

        const n1 = newDialog('警告')
        console.log(n1)

        const n2 = newDialog('文本')
        console.log(n2)

 二、单例模式变形

1、代码的问题

1. 全局多了一个变量instance

2. 传递多个参数 ,无法生效

3. 构造函数的类, 和实际使用创建的函数, 不是一个名字

2、通过闭包, 解决问题1

        class Dialog {
            constructor(title) {
                console.log('创建一个弹出框插入到页面中, 类型为: ')
                this.title = title
            }
        }

        function fn(type) {
            let instance = null
            return function newDialog() {

                if (instance === null) {
                    instance = new Dialog(type)
                }

                return instance
            }
        }

        const n1 = fn('警告')
        const res = n1()
        console.log(res)

        class Dialog {
            constructor(title) {
                console.log('创建一个弹出框插入到页面中, 类型为: ')
                this.title = title
            }
        }

        // 利用自执行函数 进一步优化
        const newDialog = (function fn() {
            let instance = null
            return function inner(type) {

                if (instance === null) {
                    instance = new Dialog(type)
                }

                return instance
            }
        })()
        const n1 = newDialog('警告')
        console.log(n1)

        const n2 = newDialog('文本')
        console.log(n2)

 3、解决问题2:传递多个参数 ,无法生效

        class Dialog {
            constructor() {
                console.log('创建一个弹出框插入到页面中, 类型为: ')
                this.title = ''
            }
            // 每次需要给title赋值, 直接调用这个方法即可
            init(title) {
                this.title = title
                console.log('当前title的值为: ', title)
            }
        }
        const newDialog = (function fn() {
            let instance = null
            return function inner(type) {

                if (instance === null) {
                    instance = new Dialog()
                }

                instance.init(type)

                return instance
            }
        })()

        const n1 = newDialog('警告')
        console.log(n1)

        const n2 = newDialog('文本')
        console.log(n2)

 4、解决 问题3:构造函数的类, 和实际使用创建的函数, 不是一个 名字

        const Dialog = (function fn() {
            let instance = null

            class Dialog {
                constructor() {
                    console.log('创建一个弹出框插入到页面中, 类型为: ')
                    this.title = ''
                }
                // 每次需要给title赋值, 直接调用这个方法即可
                init(title) {
                    this.title = title
                    console.log('当前title的值为: ', title)
                }
            }

            return function inner(type) {
                // 1. 自动帮我们创建一个对象, 自动帮我们把函数内部的this指向这个新建对象
                // 2. 手动往对象上添加属性
                // 3. 自动返回一个对象

                // 4. 构造函数内部不要写return, 返回一个基本数据类型, 写了和没写一样,
                //      如果返回一个引用数据类型, 写了构造函数就没用了

                if (instance === null) {
                    instance = new Dialog()
                }

                instance.init(type)

                return instance
            }
        })()

        // // 单例模式, 一般不建议写 new
        const n1 = Dialog('警告')
        const n2 = Dialog('文本')
        const n3 = Dialog('红色警告')

        console.log(n1)
        console.log(n2)
        console.log(n3)

        console.log(n1 === n2)
        console.log(n2 === n3)
        console.log(n1 === n3)

三、策略模式

  • 核心: 减少过多的 if...else...
  • 需求: 去购物, 购物总价1987     折扣: 8折   7折    300-30    500-50
  • 策略模式处理:  有一个数据结构,内部存储着各种折扣对应的计算总价方式
         // 70%   '300-30'   '500-50'  60%   75%
        let type = '80%';
        let total = 1987;
        if (type === '80%') {
        } else if (type === '70%') {
        } else if (type === '300-30') {
        } else if (type === '500-50') {
        } else if (type === '60%') {
        } else if (type === '75%') {
        }

(一)基础版

        const price = (function(){
            let PriceList = {
                // '80%': (total) =>{}
                '80%': total =>total * 0.8,
                '70%': total =>total * 0.7,

            }
            return function inner(type, total){
                // console.log('inner函数开始执行,计算商品总价');
                // console.log(type);
                // console.log(PriceList[type]);
                // console.log(PriceList[type](total));
                return PriceList[type](total)
            }
        })()

        let newPrice1 = price('80%', 1000);
        let newPrice2 = price('70%', 1000);
        console.log(newPrice1);
        console.log(newPrice2);

(二)进阶版

        const price = (function(){
            let PriceList = {
                // '80%': (total) =>{}
                '80%': total =>total * 0.8,
                '70%': total =>total * 0.7,
            }

            return function inner(type, total){  
                // 新增其他折扣时
                inner.add = (key, value) =>{
                    PriceList[key] = value;
                }

                // 只传递一个参数时
                inner.sub = (key) =>{
                    PriceList[key] = null
                }

                // 打印PriceList列表时
                inner.GetList = () =>{
                    return PriceList
                }
                return PriceList[type](total)
            }
        })()
        
        let newPrice1 = price('80%', 1000);
        let newPrice2 = price('70%', 1000);
        price.add('60%', total =>total * 0.6);
        let list = price.GetList();
        console.log(newPrice1);
        console.log(newPrice2);
        console.dir(price);

 四、发布订阅模式

  • 这个模式适用于大型项目的封装
  •  自行搜索:  Vue2 响应式原理
  • 除了 发布订阅模式, 还有一种叫观察者模式,这两个开发模式, 特别相似
        class observer {
            constructor(name) {
                 // 模拟一个店员(不重要)
                this.name = name   

                // 店员的记录手册
                this.message = {}
            }

            // 原型
            add(type, fn) {
                if (this.message[type] === undefined) {
                    this.message[type] = []
                }

                this.message[type].push(fn)
            }

            tri(type) {
                // 调用这个方法, 通知对应的 人员 来购买
                // console.log(type)
                // console.log(this.message[type])
                this.message[type].forEach(item => {
                    // console.log(item)
                    item()
                })
            }

            remove(type, fn) {
                // console.log(type, fn)
                // console.log(this.message[type], fn)
                this.message[type] = this.message[type].filter(item => item !== fn)
            }
        }

        const res = new observer('小方')
        console.log('初始数据: ', res)

        const fnA = () => {
            console.log('我是张三, 我想购买这本书')
        }
        const fnB = () => {
            console.log('我是李四, 我想购买这本书')
        }
        const fnC = () => {
            console.log('我是王五, 我想购买这本书')
        }

        // 新增(留下联系方式)
        res.add('JS从入门到入土', fnA)
        res.add('JS从入门到入土', fnB)
        res.add('颈椎病的预防', fnC)

        // 书本到了, 通知对应的预约者, 前来购买
        res.tri('颈椎病的预防')

        // 某人, 取消预约一本书
        res.remove('JS从入门到入土', fnA)

        console.log(res)


http://lihuaxi.xjx100.cn/news/235493.html

相关文章

jupyter notebook出现cannot import name 'create_prompt_application'问题(Died Kernel)

应该是在安装其它python第三方库时更新了prompt-toolkit版本,降级到下面的版本即可: sudo pip install prompt-toolkit1.0.15 转载于:https://www.cnblogs.com/darklights/p/10302706.html

Swift 中使用 SQLite——查询数据

本文主要介绍如何查询 SQLite 结果集,以及封装 SQLite 的操作方法。 准备测试代码 /// 从数据库中加载 person 数组 class func persons() -> [Person]? {// 1. 准备 SQLlet sql "SELECT id, name, age, height FROM T_Person;"// 2. 访问数据库// …

Eclipse创建web工程时,报错Dynamic Web Module 3.0 requires Java 1.6 or newer.

报错: 解决方案: 1.打开eclipse工具栏window->preferences 2.打开java->compiler 3.选择compiler compliance level在1.6以上版本(此处选择1.8) 4.点击apply and close保存修改,即可 转载于:https://www.cnblogs…

Django 图片上传upload_to路径指定失效的问题记录

为什么80%的码农都做不了架构师?>>> 初始方法一: 疑虑:model使用upload_to自定义路径方法失效,指定路径也失效。最后以Views中指定MEDIA_URL和MEDIA_ROOT做拼接,并且自行判断并建立文件夹,手动…

Swift 中使用 SQLite——修改和删除数据

本文主要介绍在SQLite中修改数据、删除数据&#xff1a; 更新记录 /// 将当前对象信息更新到数据库 /// /// - returns: 是否成功 func updatePerson() -> Bool {guard let name name else {print("姓名不能为空")return false}if id < 0 {print("id 不…

Maven学习总结(八)——使用Maven构建多模块项目

2019独角兽企业重金招聘Python工程师标准>>> Maven学习总结(八)——使用Maven构建多模块项目 在平时的Javaweb项目开发中为了便于后期的维护&#xff0c;我们一般会进行分层开发&#xff0c;最常见的就是分为domain&#xff08;域模型层&#xff09;、dao&#xff0…

mariadb 内存占用优化

本文由云社区发表 作者&#xff1a;工程师小熊 摘要&#xff1a;我们在使用mariadb的时候发现有时候不能启动起来&#xff0c;在使用过程中mariadb占用的内存很大&#xff0c;在这里学习下mariadb与内存相关的配置项&#xff0c;对mariadb进行调优。 查询最高内存占用 使用以下…

Swift 中使用 SQLite——新增数据

本文重点介绍两个方面&#xff0c;1、新增数据&#xff0c;2、获取自动增长 ID。 建立 Person.swift 数据模型 /// 个人模型 class Person: NSObject {// MARK: - 模型属性/// 代号var id: Int64 0/// 姓名var name: String?/// 年龄var age 0/// 身高var height: Double …