设计模式之——命令模式

相关知识:

通常设计模式有23种,主要分为三大类:

  • 创建型模式(5种):单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。
  • 结构型模式(7种):适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  • 行为型模式(11种):模板方法模式、中介者模式、策略模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、解释器模式。

前言:

命令(Command)模式 属于设计模式中的行为模式。软件开发系统中,“方法的请求者”与“方法的实现者”之间经常存在紧密的耦合关系,这不利于软件功能的扩展与维护。而命令模式就能很好地解决这个问题。

在现实生活中,命令模式的例子也很多。比如看电视时,我们只需要轻轻一按遥控器就能完成频道的切换,这就是命令模式,将换台请求和换台处理完全解耦了。电视机遥控器(命令发送者)通过按钮(具体命令)来遥控电视机(命令接收者)。

再举一个我遇到的现实例子,我们公司开发需求的流程是:产品经理在jira上建立需求(看作是创建命令),然后将需求制定给我们开发(看作是命令和开发绑定起来),然后我们评估时间给产品,接着产品下命令开发。

优点:

  1. 引入统一的抽象动作降低系统的耦合度。
  2. 扩展性好,增加或删除命令非常方便。增加与删除命令不会影响其他类,满足“开闭原则”。
  3. 方便实现 Undo 和 Redo 操作。可以结合备忘录模式,实现命令的撤销与恢复。
  4. 可以在现有命令的基础上,增加额外功能。比如日志记录,结合装饰器模式会更加灵活。

缺点:

  1. 和抽象工厂一样,会产生大量具体的命令类(因为每一个具体操作都需要设计一个具体命令类),会增加系统的复杂性。
  2. 命令模式的结果其实就是接收方的执行结果,但是为了以命令的形式进行架构、解耦请求与实现,引入了额外类型结构(引入了请求方与抽象命令接口),增加了理解上的困难。

场景与实现:

命令模式包含以下主要角色。

  1. 抽象命令类(Command)角色:声明执行命令的接口,拥有执行命令的抽象方法 execute()。
  2. 具体命令类(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
  3. 实现者/接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。
  4. 调用者/请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。

基于命令模式,实现一个我们现在开发流程的场景。

分析实现:

1.定义一个抽象命令类(命令),统一抽象方法execute()

2.创建两个具体命令类(一个具体的开始开发命令,一个具体的停止开发命令)

3.创建命令对应的接受者(开发)

4.创建命令的发起者,也就是调用者(产品经理)

5.创建测试类测试

代码实现:

项目结构图:

主要就是一个抽象命令类、两个具体命令实体,一个开发者实体类,一个产品经理实体类,测试类

相关类源码:

抽象命令类:ICommand,定义了一个抽象的命令执行方法

public abstract class ICommand {
    // 定义命令的执行方法
    public abstract void execute();
}

具体命令实体类——开始开发命令:StartDevelop

定义了一个开发者实体(命令接受者),并实现抽象类的命令执行方法

public class StartDevelop extends ICommand{
    // 命令接受者
    private Developer developer;

    public StartDevelop(Developer developer){
        this.developer = developer;
    }
    @Override
    public void execute() {
        System.out.println(developer.getName()+"开始开发需求");
    }
}

具体命令实体类——停止开发命令:EndDevelop

也是同上定义了一个开发者实体(命令接受者),并实现抽象类的命令执行方法

public class EndDevelop extends ICommand {
    // 命令接受者
    private Developer developer;

    public EndDevelop(Developer developer){
        this.developer = developer;
    }

    @Override
    public void execute() {
        System.out.println(developer.getName()+"停止开发需求");
    }
}

命令接受者——开发者:Developer,定义了开发者姓名

public class Developer {
    private String name;

    public Developer(String name){
        this.name =  name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

命令调用者(执行者)——产品经理

定义一个命令抽象实体,用来接收命令,创建一个开始执行命令的方法。

public class TechnicalManager {
    // 命令实体
    private ICommand iCommand;

    public void doCommand(){
        iCommand.execute();
    }

    public ICommand getiCommand() {
        return iCommand;
    }

    public void setiCommand(ICommand iCommand) {
        this.iCommand = iCommand;
    }
}

测试类 TestMain:

public class TestMain {
    public static void main(String[] args) {
        TechnicalManager technicalManager = new TechnicalManager();

        // 创建开发者1(命令执行者)
        Developer developer1 = new Developer("悟空");
        // 创建命令1,并绑定开发者
        ICommand command1 = new StartDevelop(developer1);

        // 技术经理下达第一个命令
        technicalManager.setiCommand(command1);
        // 技术经理命令执行命令1
        technicalManager.doCommand();

        // 创建开发者2(命令执行者)
        Developer developer2 = new Developer("八戒");
        // 创建命令2,并绑定开发者
        EndDevelop command2 = new EndDevelop(developer2);
        // 技术经理下达第二个命令
        technicalManager.setiCommand(command2);
        // 技术经理命令执行命令2
        technicalManager.doCommand();

    }
}

主要就是先创建两个命令,两个开发者,并且把开发者和命令绑定起来(相当于产品把命令分给指定的人),接下来产品指定对应的命令进行执行。

测试结果。

这样命令模式就简单实现了。如果后续还需要添加命令,那么只需要新建一个具体的命令实体类就好了,扩展性是不是很好呢,

总结:

利用命令模式能够进行类的解耦,让调用者和接受者没有任何关系,也通过对行为的抽象,让新增其他行为变得清晰容易,也就 是可扩展性大大增加。

如果对你有帮助,欢迎评论+点赞+收藏,这会鼓励我继续进行创作哟!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值