typescript实现命令模式

typescript实现命令模式

定义

命令模式将不同的请求封装成命令对象,接受者根据实际业务调用这些命令对象。

当不同的业务集中到一个方法中时,采用命令模式将每个业务作为一条命令执行,通过命令模式解除耦合。

类模型

在这里插入图片描述

  • Command接口: 包含excute(), undo()方法
  • ConcreteCommand类,具体命令,实现Command接口
  • Client类: 客户,创建命令->绑定请求者
  • Receiver类: 具体业务
  • Invoker类: 命令请求者。只接收指令并执行,不用管具体指令是什么。包含setCommand(command)

遥控器例子

有一个遥控器,上面有很多开关按钮,每个开关控制一个电器,例如开关1控制电视电灯,开关二控制电视机开和关,开关三控制电视机频道。。。如下图
在这里插入图片描述

1.Receiver-业务类,电灯和电视机

export class Light{
    on(){
        console.log('开灯')
    }
    off(){
        console.log('关灯')
    }
}
export class TV{
    channel: number = 0;
    on(){
        console.log('打开电视')
    }
    off(){
        console.log('关闭电视')
    }
    play(){
        this.channel = 12;
        console.log('播放体育频道')
    }
    // 频道+
    channelUp(){
        if (this.channel < 100) {
            this.channel ++;
            console.log('频道+,当前频道=',this.channel)
        }
    }
    // 频道-
    channelDown(){
        if (this.channel > 0) {
            this.channel --;
            console.log('频道-,当前频道=',this.channel)
        }
    }
}

2.写一个command接口

export interface Command{
    // 执行
    excute: () => void;
    // 撤销
    undo?: () => void;
}
  1. command接口实现类
import {Command} from '../Command'
import {Light} from '../../receiver/Light'
// 开灯
export class LightOn implements Command{
    private receriver: Light;
    constructor(receriver: Light){
        this.receriver = receriver;
    }
    excute(){
        this.receriver.on();
    }
}
// 关灯
export class LightOff implements Command{
    private receriver: Light;
    constructor(receriver: Light){
        this.receriver = receriver;
    }
    excute(){
        this.receriver.off();
    }
}
import {Command} from '../Command'
import {TV} from '../../receiver/TV'
// 开
export class TVOn implements Command{
    private receriver: TV;
    constructor(receriver: TV){
        this.receriver = receriver;
    }
    excute(){
        this.receriver.on();
    }
}
// 关
export class TVOff implements Command{
    private receriver: TV;
    constructor(receriver: TV){
        this.receriver = receriver;
    }
    excute(){
        this.receriver.off();
    }
}
// 播放
export class TVPlay implements Command{
    private receriver: TV;
    constructor(receriver: TV){
        this.receriver = receriver;
    }
    excute(){
        // this.receriver.on();
        this.receriver.play();
    }
}

export class ChannelUp implements Command{
    private receriver: TV;
    constructor(receriver: TV){
        this.receriver = receriver;
    }
    excute(){
        this.receriver.channelUp();
    }
    undo(){
        console.log('ChannelUp-频道撤回')
        this.receriver.channelDown()
    }
}
export class ChannelDown implements Command{
    private receriver: TV;
    constructor(receriver: TV){
        this.receriver = receriver;
    }
    excute(){
        this.receriver.channelDown();
    }
    undo(){
        console.log('ChannelDown-频道撤回')
        this.receriver.channelUp()
    }
}

4.请求者

import {Command} from './command/Command'

export class Invoker{
    private command!: Command;
    constructor(command: Command){
        this.setCommand(command);
    }
    // 设置命令
    private setCommand(command: Command){
        this.command = command;
    }
    // 执行命令
    action(){
        this.command.excute();
    }
    undo(){
        if (this.command.undo){
            this.command.undo();
        }
    }
}

5.客户端-创建命令,绑定请求者

import {Invoker} from './Invoker'
import * as LightCommand from './command/impl/Light';
import * as TVCommand from './command/impl/TV';
import {Light} from './receiver/Light'
import {TV} from './receiver/TV';

export class Client{
    private switch: Map<string,Invoker> = new Map();
    private tv: TV;
    private light: Light;
    private undo: string = '';
    constructor(){
        this.tv = new TV();
        this.light = new Light()
        this.lightOn();
        this.lightOff();
        this.tvOn();
        this.tvOff();
        this.tvPaly();
        this.tvChannelUp();
        this.tvChannelDown();

    }
    // 开灯
    private lightOn(){
        const command = new LightCommand.LightOn(this.light)
        const invoker = new Invoker(command)
        if (!this.switch.has('lightOn')){
            this.switch.set('lightOn', invoker);
        }
    }
    // 关灯
    private lightOff(){
        const command = new LightCommand.LightOff(this.light)
        const invoker = new Invoker(command)
        if (!this.switch.has('lightOff')){
            this.switch.set('lightOff', invoker);
        }
    }
    // 开电视
    private tvOn(){
        const command = new TVCommand.TVOn(this.tv)
        const invoker = new Invoker(command)
        if (!this.switch.has('tvOn')){
            this.switch.set('tvOn', invoker);
        }
    }
    private tvOff(){
        const receiver = new TV();
        const command = new TVCommand.TVOff(this.tv)
        const invoker = new Invoker(command)
        if (!this.switch.has('tvOff')){
            this.switch.set('tvOff', invoker);
        }
    }
    // 关电视
    private tvPaly(){
        const command = new TVCommand.TVPlay(this.tv)
        const invoker = new Invoker(command)
        if (!this.switch.has('tvPaly')){
            this.switch.set('tvPaly', invoker);
        }
    }
    // 电视频道+
    private tvChannelUp(){
        const command = new TVCommand.ChannelUp(this.tv)
        const invoker = new Invoker(command)
        if (!this.switch.has('tvChannelUp')){
            this.switch.set('tvChannelUp', invoker);
        }
    }
    // 电视频道-
    private tvChannelDown(){
        const command = new TVCommand.ChannelDown(this.tv)
        const invoker = new Invoker(command)
        if (!this.switch.has('tvChannelDown')){
            this.switch.set('tvChannelDown', invoker);
        }
    }
    
    // 执行
    public run(key: string){
        switch (key) {
            case 'tvUndo':
                this.switch.get(this.undo)?.undo();
                break;
            default:
                this.switch.get(key)?.action();
                this.undo = key;
                break;
        }
        
    }
    
}

测试

import {Client} from './Client'

// yarn run ts-node test.ts
(() => {
    const client = new Client();

    client.run('tvOn');
    client.run('tvPaly');
    client.run('tvChannelUp');
    client.run('tvUndo');
    client.run('')
    client.run('tvChannelDown')
    client.run('tvUndo')
    client.run('tvUndo')
})()

输出:

打开电视
播放体育频道
频道+,当前频道= 13
ChannelUp-频道撤回
频道-,当前频道= 12
频道-,当前频道= 11
ChannelDown-频道撤回
频道+,当前频道= 12
ChannelDown-频道撤回
频道+,当前频道= 13

源码
代码在github中,点击查看

参考文献:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wcc_chao@163.com

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值
>