java23种设计模式-命令模式

在阎宏博士的《JAVA与模式》一书中开头是这样描述命令(Command)模式的:bash

  命令模式属于对象的行为模式。命令模式又称为行动(Action)模式或交易(Transaction)模式。ui

  命令模式把一个请求或者操做封装到一个对象中。命令模式容许系统使用不一样的请求把客户端参数化,对请求排队或者记录请求日志,能够提供命令的撤销和恢复功能。this

1 命令模式的结构

命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分割开,委派给不一样的对象。spa

每个命令都是一个操做:请求的一方发出请求要求执行一个操做;接收的一方收到请求,并执行操做。命令模式容许请求的一方和接收的一方独立开来,使得请求的一方没必要知道接收请求的一方的接口,更没必要知道请求是怎么被接收,以及操做是否被执行、什么时候被执行,以及是怎么被执行的。设计

命令容许请求的一方和接收请求的一方可以独立演化,从而具备如下的优势:日志

  1. 命令模式使新的命令很容易地被加入到系统里。code

  2. 容许接收请求的一方决定是否要否决请求。cdn

  3. 能较容易地设计一个命令队列。对象

  4. 能够容易地实现对请求的撤销和恢复。blog

  5. 在须要的状况下,能够较容易地将命令记入日志。

下面以一个示意性的系统,说明命令模式的结构。

命令模式涉及到五个角色,它们分别是:

  • **客户端(Client)角色:**建立一个具体命令(ConcreteCommand)对象并肯定其接收者。

 ●  **命令(Command)角色:**声明了一个给全部具体命令类的抽象接口。

 ●  **具体命令(ConcreteCommand)角色:**定义一个接收者和行为之间的弱耦合;实现execute()方法,负责调用接收者的相应操做。execute()方法一般叫作执行方法。

 ●  **请求者(Invoker)角色:**负责调用命令对象执行请求,相关的方法叫作行动方法。

 ●  **接收者(Receiver)角色:**负责具体实施和执行一个请求。任何一个类均可以成为接收者,实施和执行请求的方法叫作行动方法。

2 代码示例

以开发一个项目为例,这个项目的成员分工也是采用了常规的分工方式,分为需求组(Requirement Group,简称 RG)、美工组(Page Group,简称 PG)、代码组(咱们内部还有一个比较优雅的名字:逻辑实现组,这里使用你们常常称呼的名称吧,英文缩写叫 Code Group,简称 CG)。

public abstract class Group {

    //你要和那个组讨论,你首先要找到这个组
    public abstract void find();
    //被要求增长功能
    public abstract void add();
    //被要求删除功能
    public abstract void delete();
    //被要求修改功能
    public abstract void change();
    //被要求给出全部的变动计划
    public abstract void plan();

}
复制代码
public class PageGroup extends Group {

    //首先这个美工组应该被找到吧,要不你跟谁谈?
    public void find() {
        System.out.println("找到美工组...");
    }
    //美工被要求增长一个页面
    public void add() {
        System.out.println("客户要求增长一个页面...");
    }
    //客户要求对现有界面作修改
    public void change() {
        System.out.println("客户要求修改一个页面...");
    }
    //甲方是老大,要求删除一些页面
    public void delete() {
        System.out.println("客户要求删除一个页面...");
    }
    //全部的增删改那要给出计划呀
    public void plan() {
        System.out.println("客户要求页面变动计划...");
    }

}
复制代码
public class CodeGroup extends Group {

    //客户要求代码组过去和他们谈
    public void find() {
        System.out.println("找到代码组...");
    }
    //客户要求增长一项功能
    public void add() {
        System.out.println("客户要求增长一项功能...");
    }
    //客户要求修改一项功能
    public void change() {
        System.out.println("客户要求修改一项功能...");
    }
    //客户要求删除一项功能
    public void delete() {
        System.out.println("客户要求删除一项功能...");
    }
    //客户要求出变动计划
    public void plan() {
        System.out.println("客户要求代码变动计划...");
    }

}
复制代码
public class RequirementGroup extends Group {

    //客户要求需求组过去和他们谈
    public void find() {
        System.out.println("找到需求组...");
    }
    //客户要求增长一项需求
    public void add() {
        System.out.println("客户要求增长一项需求...");
    }
    //客户要求修改一项需求
    public void change() {
        System.out.println("客户要求修改一项需求...");
    }
    //客户要求删除一项需求
    public void delete() {
        System.out.println("客户要求删除一项需求...");
    }
    //客户要求出变动计划
    public void plan() {
        System.out.println("客户要求需求变动计划...");
    }
}
复制代码

这时候客户须要修改需求了,定义出命令类:

public abstract class Command {

    //把三个组都定义好,子类能够直接使用
    protected RequirementGroup rg = new RequirementGroup(); //需求组
    protected PageGroup pg = new PageGroup(); //美工组
    protected CodeGroup cg = new CodeGroup(); //代码组;
    //只要一个方法,你要我作什么事情
    public abstract void execute();

}
复制代码
//增长一项需求
public class AddRequirementCommand extends Command {

    //执行增长一项需求的命令
    public void execute() {
        //找到需求组
        super.rg.find();
        //增长一份需求
        super.rg.add();
        //给出计划
        super.rg.plan();
    }
}
复制代码
//删除一个页面的命令
public class DeletePageCommand extends Command {

    //执行删除一个页面的命令
    public void execute() {
        //找到页面组
        super.pg.find();
        //删除一个页面
        super.rg.delete();
        //给出计划
        super.rg.plan();
    }
}
复制代码

有了定义好得需求,咱们须要一个跟客户对接得对接人:

public class Invoker {

    //什么命令
    private Command command;
    //客户发出命令
    public void setCommand(Command command){
        this.command = command;
    }
    //执行客户的命令
    public void action(){
        this.command.execute();
    }
}
复制代码

最后客户沟通修改需求:

public class Client {

    public static void main(String[] args) {
        //定义咱们的接头人
        Invoker xiaoSan = new Invoker(); //接头人就是我小三
        //客户要求增长一项需求
        System.out.println("-------------客户要求增长一项需求-----------------");
        //客户给咱们下命令来
        Command command = new AddRequirementCommand();
        //接头人接收到命令
        xiaoSan.setCommand(command);
        //接头人执行命令
        xiaoSan.action();
    }

}
复制代码

3 总结

命令模式比较简单,可是在项目中使用是很是频繁的,封装性很是好,由于它把请求方(Invoker)和执 行方(Receiver)分开了,扩展性也有很好的保障。可是,命令模式也是有缺点的,你看 Command 的子类没 有,那个若是我要写下去的可不是几个,而是几十个,这个类膨胀的很是多,这个就须要你们在项目中本身考虑 使用了。

相关文章
相关标签/搜索