Java设计模式之命令模式

介绍java

命令模式是一种行为型设计模式。在命令模式中,全部的请求都会被包装成为一个对象。设计模式

参考了一下其余关于命令模式的文章,其中有谈到说是能够用不一样的请求对客户进行参数化。对这句话的理解是,由于将请求封装成为对象,因此客户的全部操做,其实就是多个命令类的对象而已,即参数化了。

命令模式的最大的特色就是将请求的调用者与请求的最终执行者进行了解耦。调用者须要关心的仅仅是请求对象是否被执行了,对于请求对象是如何执行的,对什么进行操做的,通通不须要关心。ide

原理:命令模式中,通常有以下几个角色:ui

  • command:命令的抽象接口,其中包含execute方法。根据业务需求,有的还会包含其余通用方法如undo等。
  • concreteCommand:具体的命令实现类。每一种请求,都会映射一个具体的命令实现类。对于每一个类,都会实现execute方法,而且依赖receiver,也就是接收者对象。execute方法中,通常就是调用接收者对象的对应方法,从而实现对请求的最终处理。
  • receiver:请求的接收者,也是请求的最终的执行者,被命令实现类所依赖。
  • invoker:请求的调用者。调用者会调用全部传入的命令对象的execute方法,开启命令的执行,可是不会与最终的执行者receive耦合,二者中间是经过命令实现类进行联系和沟通的。
  • client:进行接收者对象和命令对象的建立,并创建二者之间的联系。

适用场景:涉及到“命令”、“操做”或者“控制”的场景,通常都是命令模式的适用场景。this

  • 餐厅点菜的过程,消费者(client)说要吃某几种菜(命令对象),赶快作好端上来。服务员(invoker)会记录全部点过的菜品(保存全部的命令对象),而后将订单给后厨说,按照单子作(调用全部命令对象的execute)。以后就会启动每一道菜品的制做流程。对于菜品如何烹制,与服务员是没有关系的,二者不耦合。
  • 遥控器的运行过程也能够理解成是一种命令模式的应用。假设有一个智能家居的遥控器,在面板上,能够控制电灯的开关,空调的开关(各类命令对象)。遥控器就是invoker的角色,负责实际命令的调用。而最终命令的执行,则是各类电器(receiver)来进行的。

案例

    背景:咱们以顾客点菜为例。顾客有一个菜单(invoker),可以预约甜点、牛奶、水果,取消甜点、牛奶、水果等操做。

    实现:

命令接口:spa

/**
 * @program: test
 * @description: 命令
 * @author: xingcheng
 * @create: 2018-09-02 15:16
 **/
public interface Command {

    /**
     * 执行命令
     */
    void execute();
    
}

定义receiver:设计

/**
 * @program: test
 * @description: 水果
 * @author: xingcheng
 * @create: 2018-09-02 15:18
 **/
public class Fruit {

    /**
     * 点一份水果
     */
    void orderFruit(){
        System.out.println("来一份水果");
    }

    /**
     * 取消水果
     */
    void cancelFruit(){
        System.out.println("取消水果");
    }
}

/**
 * @program: test
 * @description: 牛奶
 * @author: xingcheng
 * @create: 2018-09-02 15:22
 **/
public class Milk {

    /**
     * 点一份牛奶
     */
    void orderMilk(){
        System.out.println("来一份牛奶");
    }
    
    /**
     * 取消牛奶
     */
    void cancelMilk(){
        System.out.println("取消牛奶");
    }
}

/**
 * @program: test
 * @description: 甜点
 * @author: xingcheng
 * @create: 2018-09-02 15:17
 **/
public class Mousse {

    /**
     * 点一份甜点
     */
    void orderMousse(){
        System.out.println("来一份甜点");
    }

    /**
     * 取消甜点
     */
    void cancelMousse(){
        System.out.println("取消甜点");
    }
}

定义具体命令:code

/**
 * @program: test
 * @description: 点一份水果
 * @author: xingcheng
 * @create: 2018-09-02 15:29
 **/
public class OrderFruit implements Command{
    
    private Fruit fruit;

    public OrderFruit(Fruit fruit) {
        this.fruit = fruit;
    }

    /**
     * 执行命令
     */
    @Override
    public void execute() {
        fruit.orderFruit();
    }
}

/**
 * @program: test
 * @description: 点一份牛奶
 * @author: xingcheng
 * @create: 2018-09-02 15:25
 **/
public class OrderMilk implements Command{
    
    private Milk milk;

    public OrderMilk(Milk milk) {
        this.milk = milk;
    }

    /**
     * 执行命令
     */
    @Override
    public void execute() {
        milk.orderMilk();
    }
}

/**
 * @program: test
 * @description: 点一份甜点
 * @author: xingcheng
 * @create: 2018-09-02 15:31
 **/
public class OrderMousse implements Command{
    
    private Mousse mousse;

    public OrderMousse(Mousse mousse) {
        this.mousse = mousse;
    }

    /**
     * 执行命令
     */
    @Override
    public void execute() {
        mousse.orderMousse();
    }
}

/**
 * @program: test
 * @description: 取消水果
 * @author: xingcheng
 * @create: 2018-09-02 15:30
 **/
public class CancelFruit implements Command {
    
    private Fruit fruit;

    public CancelFruit(Fruit fruit) {
        this.fruit = fruit;
    }

    /**
     * 执行命令
     */
    @Override
    public void execute() {
        fruit.cancelFruit();
    }
}

/**
 * @program: test
 * @description: 取消牛奶
 * @author: xingcheng
 * @create: 2018-09-02 15:27
 **/
public class CancelMilk implements Command{
    
    private Milk milk;

    public CancelMilk(Milk milk) {
        this.milk = milk;
    }

    /**
     * 执行命令
     */
    @Override
    public void execute() {
        milk.cancelMilk();
    }
}

/**
 * @program: test
 * @description: 取消甜点
 * @author: xingcheng
 * @create: 2018-09-02 15:32
 **/
public class CancelMousse implements Command {
    
    private Mousse mousse;

    public CancelMousse(Mousse mousse) {
        this.mousse = mousse;
    }

    /**
     * 执行命令
     */
    @Override
    public void execute() {
        mousse.cancelMousse();
    }
}

定义菜单(invoker)对象

/**
 * @program: test
 * @description: 菜单
 * @author: xingcheng
 * @create: 2018-09-02 15:36
 **/
public class Menu {

    private List<Command> commands;

    public Menu() {
        this.commands = new ArrayList<>();
    }

    /**
     * 记录顾客须要什么
     */
    public void writeMenu(Command command){
        commands.add(command);
    }

    /**
     * 将菜单交给厨师
     */
    public void giveCooker(){
        if (commands != null && commands.size() > 0){
            commands.forEach(command -> command.execute());
        }
    }
}

顾客购买:blog

/**
 * @program: test
 * @description: 顾客
 * @author: xingcheng
 * @create: 2018-09-02 15:34
 **/
public class Consumer {
    
    public static void main(String[] args) {
        Fruit fruit = new Fruit();
        Milk milk = new Milk();
        Mousse mousse = new Mousse();

        // 店小二记录菜单
        System.out.println("店小二记录菜单----------------------------------------------");
        Menu menu = new Menu();
        menu.writeMenu(new OrderFruit(fruit));
        menu.writeMenu(new OrderMilk(milk));
        menu.writeMenu(new OrderMousse(mousse));
        
        // 店小二将菜单交给厨师
        menu.giveCooker();

        // 顾客取消菜单--太贵了不吃了╭(╯^╰)╮
        System.out.println("顾客取消菜单--太贵了不吃了╭(╯^╰)╮----------------------------");
        Menu menuCancel = new Menu();
        menuCancel.writeMenu(new CancelFruit(fruit));
        menuCancel.writeMenu(new CancelMilk(milk));
        menuCancel.writeMenu(new CancelMousse(mousse));
        menuCancel.giveCooker();

        System.out.println("宏命令----------------------------");
        List<Command> commands = new ArrayList<>();
        commands.add(new CancelFruit(fruit));
        commands.add(new CancelMilk(milk));
        commands.add(new CancelMousse(mousse));
        MutilCommand mutilCommand = new MutilCommand(commands);
        mutilCommand.giveCooker();
    }
    
}

结果:

延伸:

命令模式中有一种扩展,叫作宏命令,能同时进行一组命令的执行。好比遥控器只存在两个按键,一个控制全部电器的开启,一个控制全部电器的关闭。那么咱们不须要改动已有的代码,只要扩展一个组合命令类,其中包含多个命令便可。

/**
 * @program: test
 * @description: 宏命令(组合命令)
 * @author: xingcheng
 * @create: 2018-09-02 15:59
 **/
public class MutilCommand {

    private List<Command> commands;

    public MutilCommand(List<Command> commands) {
        this.commands = commands;
    }

    /**
     * 记录顾客须要什么
     */
    public void writeMenu(Command command){
        commands.add(command);
    }

    /**
     * 将菜单交给厨师
     */
    public void giveCooker(){
        if (commands != null && commands.size() > 0){
            commands.forEach(command -> command.execute());
        }
    }
    
}

总结:

命令模式的核心思想就是将命令或者请求封装成对象,分离请求调用者和请求最终执行者。

优势:将请求调用者和执行者解耦,适用于底层接口封装,能够经过只增长类就能够实现接口扩展,不须要修改原来的代码。

缺点:若是存在较多的命令或者请求,须要较多的命令类。

相关文章
相关标签/搜索