5. 设计模式之装饰模式

装饰模式:动态地给一个对象添加一些额外的指责,就增加功能来说,装饰模式比生成子类更加灵活

「装饰模式」对于前端开发者而言一定是非常熟悉的,什么是「装饰模式」呢?顾名思义,「装饰模式」就像是给一个类穿上一件一件衣服,通过不同的搭配,让这个类呈现出不同的特点。那我们在工作的过程中,在编写页面的时候,做的好像也是一样的事情对吧?比如按钮组件,他会有defaultprimaryhoveractivedisabled等等状态,我们常用的方式就是通过给button添加不同的class来实现这种种不同的效果,其实这种实现的方式,就是「装饰模式」的应用。只不过今天我们说的是「装饰模式」在JS中的应用而已,我们可以通过CSS的思维来帮助我们理解。

实例:当下我们需要做一套考试系统,一套试卷由一道道试题组成,试题会有练习、考试和解析3种状态:

  • 练习状态下,试题需要显示题干和选项
  • 考试状态下,试题需要显示题干、选项和分数
  • 解析状态下,题干需要显示题干、选项、分数和解析

由上我们可以想象出具体的实现模式就是根据源数据在不同条件下显示不同的状态和内容,就可以结合「装饰模式」来实现。

// 试题渲染
class Question {
    constructor(question) {
        this.question = question;
    }
    
    render() {
        console.log(this.question.topic);
        console.log(this.question.options);
    }
}

// 分数渲染装饰器
class ScoreQuestion {
    constructor(question) {
        this.question = question;
    }
    
    render() {
        this.question.render();
        console.log(this.question.question.score);
    }
}

// 解析渲染装饰器
class AnalyzeQuestion {
    constructor(question) {
        this.question = question;
    }
    
    render() {
        this.question.render();
        console.log(this.question.question.analyse);
    }
}

const question = {
    topic: '题干',
    options: '选项一、选项二、选项三',
    score: 10,
    analyse: '选项一是正确答案'
};

let instance = new Question(question);
instance.render();
// 题干
// 选项一、选项二、选项三

instance = new ScoreQuestion(instance);
instance.render();
// 题干
// 选项一、选项二、选项三
// 10

instance = new AnalyzeQuestion(instance);
instance.render();
// 题干
// 选项一、选项二、选项三
// 10
// 选项一是正确答案

总结

如果我们实现一项功能可以做到将核心指责与装饰功能区分的话,就可以使用「装饰模式」来实现。「装饰模式」的优点就在于把类中的装饰功能从类中搬移去除,这样可以简化原有的类


参考

大话设计模式 -- 程杰