二哈谈设计模式之命令模式

命令模式



前言

  • 概念
    将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。也称之为:动作Action模式、事务transaction模式
  • 结构
    Command抽象命令类:定义命令接口,声明执行方法
    ConcreteCommand具体命令类:命令接口的实现对象,通常会持有接收对者,并调用接受者的功能来完成命令要执行的操作。
    Invoker调用者/请求者:请求的发送者,它通过命令对象来执行请求。一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令类之间存在关联。在程序运行时,将调用命令对象的execute(),间接调用接收者的相关操作。
    Receiver接收者:接收者执行与请求相关的操作,具体实现对请求的业务处理。未抽象前,实际执行操作内容的对象。
    Client客户类:在客户类中需要创建调用者对象、具体命令类对象,在创建具体命令对象时指定对应的接收者。发送者和接收者之间没有直接关系,都通过命令对象间接调用。

一、具体实现

以电脑开机为例,其具体流程为:
按下按钮,按钮本身不知道如何处理,通过连接线来请求主板,让主板去完成真正的启动机器。其中,机箱的按钮相当于是命令对象;机箱相当于Invoker;主板相当于接收者;命令对象持有一个接受者,就相当于给机箱的按钮脸上了一根连接线;当机箱上的按钮被按下时,机箱就把这个命令通过连接线发送了出去。

1.抽象主板(抽象接收者)

/**
 * 主板接口
 */
public interface MainBoardApi {
    /**
     * 主板具有开机功能
     */
    public void open();
}

2.主板实现(接收者)

public class GigaMainBoard implements MainBoardApi {
    /**
     * 真正的开机命令
     */
    @Override
    public void open() {
        System.out.println("华硕主板现在开机,请等候");
        System.out.println("接通电源...");
        System.out.println("设备检查...");
        System.out.println("装载系统...");
        System.out.println("机器正常运转起来...");
        System.out.println("机器已经正常打开,请操作...");
    }
}

3.抽象命令接口

/**
 * 命令接口
 */
public interface Command {
    /**
     * 执行命令对应的操作
     */
    public void execute();
}

4.具体命令

/**
 * 开机命令的实现
 */
public class OpenCommand implements Command {
    /**
     * 持有真正命令的接收者——主板对象
     */
    private  MainBoardApi mainBoard = null;

    public OpenCommand(MainBoardApi mainBoard) {
        this.mainBoard = mainBoard;
    }

    @Override
    public void execute() {
        //对于命令对象,根本不知道如何开机,会转调主板对象
        //让主板去完成开机的功能
        this.mainBoard.open();
    }
}

5.提供机箱(调用者)

/**
 * 机箱对象
 */
public class Box {
    /**
     * 开机命令对象
     */
    private Command openCommand ;
    /**
     * 设置开机命令对象
     */
    public void setOpenCommand(Command openCommand) {
        this.openCommand = openCommand;
    }
    public void openButtonPressed(){
        //按下按钮,执行命令
        openCommand.execute();
    }
}

6.客户类

/**
 * 客户类
 */
public class Client {
    public static void main(String[] args) {
        //1.把命令与真正的实现组合起来,相当于在组装机器
        MainBoardApi mainBoard = new GigaMainBoard();
        OpenCommand openCommand = new OpenCommand(mainBoard);
        //2.为机箱上的按钮设置对应的命令,让按钮知道该干什么
        Box box = new Box();
        box.setOpenCommand(openCommand);
        //3.然后模拟按下机箱上的按钮
        box.openButtonPressed();
    }
}

结果:
在这里插入图片描述

二、应用场景

  • Struts2中,action的整个调用过程中就有命令模式。
  • 数据库事务机制的底层实现
  • 命令的撤销和恢复

总结

  • 优点:
    1.更松散的耦合
    2.更动态的控制
    3.能很自然地复合命令
    4.更好的扩展性
  • 场景:
    1.如果需要抽象出需要执行的动作,并参数化这些对象,可以选用命令模式,把这些需要执行的动作抽象成为命令,然后实现命令的参数化配置。
    2.如果需要在不同的时刻指定、排列和执行请求,可以选用命令模式,把这些请求封装成为命令对象,然后实现把请求队列化。
    3.如果需要支持取消操作,可以选用命令模式,通过管理命令对象,能很容易地实现命令的恢复和重做的功能。
    4.如果需要当系统崩溃时,能把对系统的操作功能重新执行一遍,可以选用命令模式,把这些操作功能的请求封装成命令对象,然后实现日志命令,就可以在系统恢复回来后,通过日志获取命令列表,从而重新执行一遍功能。
    5.在需要事务的系统中,可以选用命令模式,命令模式提供了对事务进行建模的方法,命令模式有一个别名,就是Transaction。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值