前端设计模式-深入思考?

前面几天,写了一些面试题,应付一下后续的面试。
最近打算把自己的缺点优化一下,怎么说呢,其实很喜欢学习,接触自己不懂的东西,我一开始会有一个缺点,就是我会走的很快,这个走的很快是指,学习很东西,没有去把自己学习的东西进行一个深度的学习,之前自己学习的就是皮毛,我接下来会进行一个深入的学习,之前学习的东西进行一个深度的思考。

思考-如果没有设计模式会怎么样?

刚开始接触前端的时候,写代码是没有使用设计模式的,比如一个简单的 if else 判断自己会写很长的判断,在可读性来说是很差的,后续的同事接手代码的时候,看到很长的if else也会很难理解。
写代码的基本要求就是自己看的懂,别人也要看的懂。

总结上面的废话来说,针对业务逻辑变得复杂多样了,就需要提高代码的可读性和维护性

设计模式的五种基本原则

开放-封闭原则

开放指的是在新增,对扩展开放
封闭指的是 不要修改我们之前的源码
总结就是 不用修改源码就能扩展功能

单一职责原则

我们的模块只做一件事件,模块职责越单一越好

依赖倒置原则

上层模块不能依赖具体的下层模块,应该依赖抽象模块

// 具体层 (下层模式)
function Like1 () {}
function Like2 () {}
function Like3 () {}

// 抽象模式
function likeItem(like) {
	let res = {
	like1: new Like1(),
	like2: new Like2(),
	like3: new Like3(),
	}
	return res[like]

}

// 上层模式
function likes (like) {
	return likeItem(like1)
}
likes('like1')
接口隔离原则

接口要细化,功能要单一,一个接口不要调用太多方法
单一职责原则主要关注于模块本身,接口隔离原则关注于接口;
我们尽量细化接口,每个接口做的事情尽量单一化。

里氏替换原则

主要用于继承,它的意义就是任何使用父类的地方都可以使用子类去替换,更加直白的说,子类在继承父类的时候,子类必须完全保证继承父类的属性和方法,这样的话,可以使用父类的地方,也可以使用子类替换。

工厂模式

  • 原则

符合开放-封闭原则
构造函数和创建者分离

  • 使用场景

jq - $(‘div’)
React.createElement
vue 异步组件

简单的工厂模式
        class Father {
            getInfo(val) {
                console.log(val);
            }
        }

        class Click extends Father {

        }

        class Confirm extends Father {

        }

        class Cancel extends Father {

        }

        class Popup {
            static buildPopup(val) {
                switch (val) {
                    case 'add':
                        return new Click().getInfo('数值加法')

                    case 'sub':
                        return new Confirm().getInfo('数值减法')

                    case 'take':
                        return new Cancel().getInfo('数值乘法')
                    default:
                        break;
                }
            }
        }

        let p = Popup.buildPopup('add')
        let p1 = Popup.buildPopup('sub')
        let p2 = Popup.buildPopup('take')
抽象的工厂模式
    	class Product {
            constructor(num1, num2) {
                this.num1 = num1
                this.num2 = num2
            }

            add() {
                console.log('数值相加', this.num1 + this.num2);
            }

            sub() {
                console.log('数值相减', this.num1 - this.num2);
            }

            take() {
                console.log('数值相乘', this.num1 * this.num2);

            }
        }

        class CreatCount {
            create(val1, val2) {
                return new Product(val1, val2)
            }
        }

        let c = new CreatCount()
        let p = c.create(2, 3)
        p.add()
        p.sub()
        p.take()

单例模式

单例模式是我接触的第一模式
使用场景

登录框的显示和隐藏,还是就是组件重用的弹出框的显示和隐藏
单例模式的经典是: 只会创建一个对象,公用一个实例对象

	 class SingleObject {
            show() {
                console.log('展示弹出框');
            }
            hide() {
                console.log('隐藏弹出框');
            }
        }
        SingleObject.getInstance = (function () {
            let instance = null
            return function () {
                if (!instance) {
                    instance = new SingleObject()
                }
                return instance
            }
        })()

        let p = SingleObject.getInstance()
        p.show()
        p.hide()
        console.log(p.show() === p.hide());

策略模式

策略模式在工作中可能是用的最多的了
原则:

  1. 符合开放封闭原则
  2. 不同策略分开处理
   		function strategy(type, a, b) {
            let typeData = {
                'add': function (a, b) {
                    return a + b
                },
                'sub': function (a, b) {
                    return a - b
                },
            }
            return typeData[type](a, b)
        }
        let res = strategy('add', 2, 3)
        console.log(res);

外观模式

外观模式是提供了一个统一的接口来简化接口
不符合单一原则,和开放封闭原则
下面有两个案例可以看下

		// 接口A
    	function getName() {
    	        return 'zs'
        }
		// 接口B
        function getAge() {
            return 18
        }
		// 统一管理接口A 和 B
        function getAllInfo(FnName, Fnage) {
            let info = FnName() + '-' + Fnage()
            return info

        }
        getAllInfo(getName, getAge)
        
  		 class E {
            stopPropagation() {
                console.log('阻止冒泡事件');
            }
            preventDefault() {
                console.log('阻止默认行为');
            }
       	 }

        var stopEvent = function (e) {  //同时阻止事件默认行为和冒泡
            e.stopPropagation();
            e.preventDefault();
        }
        stopEvent(new E())

迭代器模式

适用于

顺序遍历有序集合
使用者不必知道集合的内部结构

迭代器对象和目标对象分离
迭代器将使用者与目标对象隔开
符合开放封闭原则

实现的代码

       class Iterator {
            constructor(param) {
                this.list = param.list
                this.index = 0
            }
            next() {
                if (this.hasNext()) {
                    return this.list[this.index++]
                }
                return null
            }
            hasNext() {
                if (this.list.length > this.index) {
                    return true
                }
                return false
            }
        }

        class Container {
            constructor(list) {
                this.list = list
            }
            getIterator() {
                return new Iterator(this)

            }
        }
        let res = [1, 2, 3, 4]
        let p = new Container(res)
        p = p.getIterator()
        while (p.hasNext()) {
            console.log(p.next());
        }
发布订阅模式

事件模拟场景

有这样的一个事件场景 张三 李四 王五 关注了一个中介,
张三和李四关注的是 10-20万 王五关注的是 30-50万
中介公司如果发布了 10-20 只通知张三和李四不通知王五

		 class E {
            constructor() {
                this._callback = []
            }

            on(fn) {
                this._callback.push(fn)
            }

            emit(value, type) {
                this._callback.forEach((callback) => {
                    if (callback.type === type) {
                        callback.fn(value)
                    }
                })
            }
        }

        // 分类别订阅 type 1 中央  2 财经
        let p = new E()
        p.on({
            type: 1,
            fn: function (value) {
                console.log('张三订阅了10-20', value);
            }
        })
        p.on({
            type: 1,
            fn: function (value) {
                console.log('李四订阅了10-20', value);
            }
        })
        p.on({
            type: 2,
            fn: function (value) {
                console.log('王五订阅了30-50', value);
            }
        })

        p.emit('中介发布了10-20万房屋信息', 1)
        p.emit('中介发布了30-50万房屋信息', 2)
观察者模式

有这样的一个场景
父母观察孩子的心情, 父母是观察者 孩子是被观察者

 		// 被观察者 孩子
        class Subscribe {
            constructor(name, state) {
                this.name = name
                this.state = state
                this.observe = []
            }
            // 父亲和母亲观察孩子
            attach(that) {
                this.observe.push(that)
            }

            // 孩子心情改变时 父母是要被通知到的
            setState(state) {
                this.state = state
                this.observe.forEach((v) => {
                    v.updata(this)
                })
            }
        }

        // 观察者 也就是孩子的父亲和母亲
        class Observe {
            constructor(name) {
                this.name = name
            }
            // 孩子心情发生改变时,这个函数被调用,父母就会知道孩子的心情变化
            updata(that) {
                console.log(`${this.name} 知道了 ${that.name} ${that.state}`);
            }
        }

        let baby = new Subscribe('宝贝', '开心')
        let father = new Observe('父亲')
        let monther = new Observe('母亲')
        baby.attach(father)
        baby.attach(monther)
        baby.setState('不开心')

tip: 在一定程度上来说,发布订阅就是 观察者模式,由于发布订阅模式的流行,就被区分开来了
观察者: 观察者直接订阅主题,当主题被激活的时候,就会触发观察者里的事件
发布订阅模式:订阅者把自己想要订阅的事件注册到调度中心,当发布者发布该事件到调度中心,也就是该事件触发时,由调度中心统一调度,订阅者注册到调度中心的处理代码

装饰器模式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值