【面试题】 ES6 类聊 JavaScript 设计模式之行为型模式(二)_js new subject

  • 观察者模式:Observer
  • 访问者模式:Visitor
  • 策略模式:Strategy
  • 状态模式:State
  • 模板方法模式:Template Method

  1. 观察者模式:Observer

观察者模式是一种关键的行为设计模式,它定义了对象之间的一对多依赖关系,以便当一个对象(发布者)更改其状态时,所有其他依赖对象(订阅者)都会收到通知并自动更新。也称为 PubSub(发布者/订阅者)或事件调度程序/侦听器模式。发布者有时称为主体,订阅者有时称为观察者。

观察者模式是一种软件设计模式,其中一个名为主体的对象维护其依赖项列表,称为观察者,并自动通知他们任何状态更改,通常通过调用他们的方法之一。 —— 维基百科

实例

将创建了一个简单的 Subject 类,它具有从订阅者集合中添加和删除 Observer 类对象的方法。将 Subject 类对象中的任何更改传播到订阅的观察者的方法 fire

class Subject {
    constructor() {
        this._observers = [];
    }

    subscribe(observer) {
        this._observers.push(observer);
    }

    unsubscribe(observer) {
        this._observers = this._observers.filter((obs) => observer !== obs);
    }

    fire(change) {
        this._observers.forEach((observer) => {
            observer.update(change);
        });
    }
}

class Observer {
    constructor(state) {
        this.state = state;
        this.initialState = state;
    }

    update(change) {
        const state = this.state;
        const handlers = {
            inc: (num) => ++num,
            dec: (num) => --num,
        };
        const changeMethod = handlers[change.toLowerCase()];
        this.state = changeMethod ? changeMethod(state) : this.initialState;
    }
}

// 使用
const sub = new Subject();

const obs1 = new Observer(1);
const obs2 = new Observer(19);

sub.subscribe(obs1);
sub.subscribe(obs2);

sub.fire("INC");

console.log(obs1.state); // 2
console.log(obs2.state); // 20
复制代码
  1. 访问者模式:Visitor

访问者模式向对象添加操作而无需修改它们。

访问者模式是一种将算法与其操作的对象结构分离的方法。这种分离的实际结果是能够在不修改结构的情况下向现有对象结构添加新操作。—— 维基百科

实例

将举一个数学表达式 NumberExpression 的例子,列出给定的算术表达式。

class NumberExpression {
    constructor(value) {
        this.value = value;
    }

    print(buffer) {
        buffer.push(this.value.toString());
    }
}

class AdditionExpression {
    constructor(left, right) {
        this.left = left;
        this.right = right;
    }

    print(buffer) {
        buffer.push("(");
        this.left.print(buffer);
        buffer.push("+");
        this.right.print(buffer);
        buffer.push(")");
    }
}
复制代码

使用方式如下:

const e = new AdditionExpression(
    new NumberExpression(6),
    new AdditionExpression(new NumberExpression(2), new NumberExpression(8))
);

const buffer = [];
e.print(buffer);
console.log(buffer.join(""));
复制代码

输出结果如下:

(6+(2+8))
复制代码
  1. 策略模式:Strategy

策略模式允许在某些情况下选择其中一种算法。允许为特定任务封装替代算法。它定义了一系列算法并以这样一种方式封装它们,即它们在运行时可互换,而无需客户干预或知识。

策略模式是一种行为软件设计模式,可以在运行时选择算法。代码不是直接实现单个算法,而是接收运行时指令,以确定要使用一系列算法中的哪一个。 —— 维基百科

实例

将举一个例子,有一个文本处理器,将根据策略(HTML 或 Markdown)输出列表数据格式。

const OutputFormat = Object.freeze({
    markdown: 0,
    html: 1,
});

class ListStrategy {
    start(buffer) {}
    end(buffer) {}
    addListItem(buffer, item) {}
}

class MarkdownListStrategy extends ListStrategy {
    addListItem(buffer, item) {
        buffer.push(` * ${item}`);
    }
}

class HtmlListStrategy extends ListStrategy {
    start(buffer) {
        buffer.push("<ul>");
    }
    end(buffer) {
        buffer.push("</ul>");
    }
    addListItem(buffer, item) {
        buffer.push(`   <li>${item}</li>`);
    }
}
复制代码

创建 TextProcessor 类

class TextProcessor {
    constructor(outputFormat) {
        this.buffer = [];
        this.setOutputFormat(outputFormat);
    }

    setOutputFormat(format) {
        switch (format) {
            case OutputFormat.markdown:
                this.listStrategy = new MarkdownListStrategy();
                break;
            case OutputFormat.html:
                this.listStrategy = new HtmlListStrategy();
                break;
        }
    }

    appendList(items) {
        this.listStrategy.start(this.buffer);
        for (const item of items) {
            this.listStrategy.addListItem(this.buffer, item);
        }
        this.listStrategy.end(this.buffer);
    }

    clear() {
        this.buffer = [];
    }

    toString() {
        return this.buffer.join("\n");
    }
}
复制代码

下面是使用方式:

console.log("==============Markdown===============")
const tp = new TextProcessor();
const arrayItems = ["第一条", "第二条", "第三条"];
tp.setOutputFormat(OutputFormat.markdown);
tp.appendList(arrayItems);
console.log(tp.toString());

console.log("==============HTML===============")
tp.clear();
tp.setOutputFormat(OutputFormat.html);
tp.appendList(arrayItems);
console.log(tp.toString());
复制代码

输出结果如下:

==============Markdown===============
 * 第一条
 * 第二条
 * 第三条
==============HTML===============
<ul>
   <li>第一条</li>
   <li>第二条</li>
   <li>第三条</li>
</ul>
复制代码
  1. 状态模式:State

状态模式允许对象根据其内部状态的变化来改变其行为。状态模式类返回的对象似乎改变了它的类。它为一组有限的对象提供特定于状态的逻辑,其中每个对象类型代表一个特定的状态。

状态模式是一种行为软件设计模式,它允许对象在其内部状态发生变化时改变其行为。这种模式接近于有限状态机的概念。 —— 维基百科

实例

最后

最后写上我自己一直喜欢的一句名言:世界上只有一种真正的英雄主义就是在认清生活真相之后仍然热爱它

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值