命令模式

定义

命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

在软件系统中,方法的请求者与方法的实现者总是存在着紧密的耦合关系,这不利于扩展和维护。因此“如何将方法的请求者与方法的实现者解耦?”变得很重要,命令模式能很好地解决这个问题。
在现实生活中,我们想看电视,只要按遥控器的开关即可,而不用知道电视机内部怎么实现的。

角色

命令模式通用类图如下图
在这里插入图片描述
Command抽象命令接口:所有要执行的命令会在这里声明。
ConcreteCommand具体命令:它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
Receiver接收者:命令传到这里来会被执行
Invoker调用者:接受命令,并执行命令

举例实现

就拿我们平常对数据库的增删改查举例
数据库类(Receiver)

package factory.command;

public class DataBase {

    public void add(){
        System.out.println("添加数据。。。");
    }

    public void del(){
        System.out.println("删除数据。。。");
    }

    public void modify(){
        System.out.println("修改数据。。。");
    }

    public void select(){
        System.out.println("查询数据。。。");
    }
}

JDBC(Receiver)

package factory.command;

public class JDBC {

    public void getConnect(){
        System.out.println("获取连接。。。");
    }

    public void transfer(){
        System.out.println("传递指令。。。");
    }

    public void returnData(){
        System.out.println("返回结果。。。");
    }
}

Command

package factory.command;

public abstract class Command {

    protected DataBase dataBase = new DataBase();

    protected JDBC jdbc = new JDBC();

    public abstract void execute();
}

ConcreteCommand

//AddCommand
package factory.command;

public class AddCommand extends Command {
    @Override
    public void execute() {
        super.jdbc.getConnect();
        super.jdbc.transfer();
        super.dataBase.add();
        super.jdbc.returnData();
    }
}
//DelCommand
package factory.command;

public class DelCommand extends Command {
    @Override
    public void execute() {
        super.jdbc.getConnect();
        super.jdbc.transfer();
        super.dataBase.del();
        super.jdbc.returnData();
    }
}
//ModifyCommandi
package factory.command;

public class ModifyCommand extends Command {
    @Override
    public void execute() {
        super.jdbc.getConnect();
        super.jdbc.transfer();
        super.dataBase.modify();
        super.jdbc.returnData();
    }
}
//SelectCommand
package factory.command;

public class SelectCommand extends Command {
    @Override
    public void execute() {
        super.jdbc.getConnect();
        super.jdbc.transfer();
        super.dataBase.select();
        super.jdbc.returnData();
    }
}

Invoker调用者

package factory.command;

public class Invoker {

    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void action(){
        this.command.execute();
    }
}

测试类

package factory.command;

public class Client {

    public static void main(String[] args) {
        //定义调用者
        Invoker invoker = new Invoker();
        //创建命令
        Command command = new AddCommand();
        //调用者接受命令
        invoker.setCommand(command);
        //执行命令
        invoker.action();
    }
}

结果如下
在这里插入图片描述

优点
  1. 降低系统的耦合度:调用者与接收者之间没有依赖关系,调用者只要调用command与抽象类的execute就可以了
  2. 增加或删除命令非常方便:采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。
  3. 更动态的控制:命令模式把请求封装起来,可以动态地对它进行参数化、队列化和日志化等操作,从而使得系统更灵活。
  4. 复合命令:命令模式中的命令对象能够很容易地组合成复合命令,也就是宏命令,从而使系统操作更简单,功能更强大
缺点

可能产生大量具体命令类。因为计对每一个具体操作都需要设计一个具体命令类,这将增加系统的复杂性。

扩展

参考自:这里

  1. 宏命令
    宏命令又称为组合命令,它是命令模式和组合模式联用的产物。
    宏命令也是一个具体命令,不过它包含了对其他命令对象的引用,在调用宏命令的execute()方法时,将递归调用它所包含的每个成员命令的execute()方法,一个宏命令的成员对象可以是简单命令,还可以继续是宏命令。执行一个宏命令将执行多个具体命令,从而实现对命令的批处理。
  2. 撤销命令
    有两种基本的思路来实现可撤销的操作:
     逆向操作实现:比如被撤销的操作是添加功能,那撤消的实现就变成删除功能;同理被撤销的操作是删除功能,那么撤销的实现就变成添加功能。
     存储恢复实现,意思就是把操作前的状态记录下来,然后要撤销操作的时候就直接恢复回去就可以了,可使用备忘录模式(Memento Pattern)来实现。
  3. 命令队列
    有时候我们需要将多个请求排队,当一个请求发送者发送一个请求时,将不止一个请求接收者产生响应,这些请求接收者将逐个执行业务方法,完成对请求的处理。此时,我们可以通过命令队列来实现。
    命令队列的实现方法有多种形式,其中最常用、灵活性最好的一种方式是增加一个CommandQueue类,由该类来负责存储多个命令对象,而不同的命令对象可以对应不同的请求接收者。
  4. 请求日志
    概念:将所有的动作都记录在日志中,并能在系统死机后,重新调用这些动作恢复到之前的状态。当我们执行命令的时候,将历时记录存储在磁盘中。一旦系统死机,我们就可以将命令对象重新加载,并依次调用这些对象的execute()方法。
    实现方法:利用对象的序列化把对象保存起来(记录日志),在需要的时候反序列化(恢复事务)。
    请求日志文件可以实现很多功能,常用功能如下:
      1、什么事情都存在意外,如一旦系统发生故障,日志文件可以为系统提供一种恢复机制,在请求日志文件中可以记录用户对系统的每一步操作,从而让系统能够顺利恢复到某一个特定的状态;
      2 、请求日志也可以用于实现批处理,在一个请求日志文件中可以存储一系列命令对象,例如一个命令队列;
      3、可以将命令队列中的所有命令对象都存储在一个日志文件中,每执行一个命令则从日志文件中删除一个对应的命令对象,防止因为断电或者系统重启等原因造成请求丢失,而且可以避免重新发送全部请求时造成某些命令的重复执行,只需读取请求日志文件,再继续执行文件中剩余的命令即可。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值