结构型设计模式之装饰器模式

76 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情

前言

装饰者模式:在不改变原对象的基础上,通过对其进行包装拓展(添加属性或者方法)使原有对象可以满足用户的更复杂需求。

这都2022年了,相信大家对ES6已经很熟悉了。在ES6中提到了一个新的语法——装饰器,用来注释或修改类和类方法。

没错,相信机智的你已经知道我要说什么了。装饰器其实就是一种变相的装饰器模式。

装饰器

假设我们有这样一个用来描述人的类——Person,这个类有个name方法用来获取这个人的完整姓名。

    class Person {
        name() { 
            return `${this.first} ${this.last}`; 
        }
    }

这个时候我们需要处理这个方法添加日志,以方便我们知道什么时候获取过这个人的姓名,然后上报给日志系统。

    function log(target, name, descriptor) {
        const oldValue = descriptor.value;
        
        descriptor.value = function() {    
            // ...上报
            return oldValue.apply(this, arguments);
        };
        
        return descriptor;
    }

看到这里,就要引出我们下一位登场的主角了——劫持函数。是的,装饰器其实也运用了函数劫持这个方法。相信这个时候大家也可以得出一个新的结论了:函数劫持也是装饰器模式的运用。

函数劫持

假设我们在做小程序端日志相关的功能,这个时候我们就需要收集错误信息然后上报给服务端。但是,如果收集错误信息呢?

大多数的错误都会冒泡的onError事件中来,但是,通过查找文档我们发现,微信小程序的脚本错误和api错误都会触发APP.onError钩子,所以我们就可以在onError钩子中做处理。

    App {
        onError(msg) {
            // 上报错误
            ...
        }
    }

但是,这种方式对业务代码的侵入比较强,而且跟业务逻辑进行了耦合。随着业务的发展,最终有可能会朝着代码屎山的方向发展,这个时候我们就需要使用装饰器模式对代码进行优化处理。

    const originError = App.onError;
    
    App.onError = function (..agus) {
        // 上报错误
        originError.apply(this, agus);
    }

结语

相信到这里大家已经对装饰器模式很熟悉了,这里我们再进行总结一下。装饰器模式是对原有函数功能不影响的前提下,进行新的功能的增强与拓展。

好了,有关装饰器模式的内容我们就聊到这里了,希望对大家有所帮助。欢迎大家在下方进行留言交流。