设计模式(十五)命令模式

作者: 我犟不过你 | 来源:发表于2021-01-12 16:51 被阅读0次

1、概述

命令模式是一种行为设计模式, 它可将请求转换为一个包含与请求相关的所有信息的独立对象。 该转换让你能根据不同的请求将方法参数化、 延迟请求执行或将其放入队列中, 且能实现可撤销操作。

在java中本质可以理解为是以接口作为参数传递。

2、适用场景

1)如果你需要通过操作来参数化对象, 可使用命令模式。
2)如果你想要将操作放入队列中、 操作的执行或者远程执行操作, 可使用命令模式。
3)如果你想要实现操作回滚功能, 可使用命令模式。

3、实例

有以下场景:

有一个饭店,饭店内有东北菜师傅和川菜师傅,还有一个店小二。
初始负责做菜,小二负责给客户点菜和通知厨师做菜。

厨师接口:

/**
 * 厨师接口
 * @date: 2021/1/12
 * @author weirx
 * @version 3.0
 */
public interface ICooker {

    /**
     * 烹饪
     */
    void doCooking();

    /**
     * 停止烹饪
     */
    void stopCooking();
}

菜品接口:

/**
 * 菜品接口
 * @date: 2021/1/12
 * @author weirx
 * @version 3.0
 */
public interface IDishes {

    /**
     * 下单
     */
    void order();

    /**
     * 退单
     */
    void back();
}

川菜厨师:

/**
 * 四川厨师
 * @date: 2021/1/12
 * @author weirx
 * @version 3.0
 */
public class SichuanCooker implements ICooker{
    @Override
    public void doCooking() {
        System.out.println("四川厨师正在烹饪");
    }

    @Override
    public void stopCooking() {
        System.out.println("四川厨师停止烹饪了");
    }
}

东北菜厨师:

/**
 * 东北厨师
 * @date: 2021/1/12
 * @author weirx
 * @version 3.0
 */
public class NortheastCooker implements ICooker{
    @Override
    public void doCooking() {
        System.out.println("东北厨师正在烹饪");
    }

    @Override
    public void stopCooking() {
        System.out.println("东北厨师停止烹饪了");
    }
}

川菜:

/**
 * 四川菜
 * @date: 2021/1/12
 * @author weirx
 * @version 3.0
 */
public class SichuanDishes implements IDishes{
    private ICooker cooker;

    public SichuanDishes(ICooker cooker) {
        this.cooker = cooker;
    }
    @Override
    public void order() {
        System.out.println("顾客下单四川菜");
        cooker.doCooking();
    }

    @Override
    public void back() {
        System.out.println("顾客取消四川菜订单了");
        cooker.stopCooking();
    }
}

东北菜:

/**
 * 东北菜
 * @date: 2021/1/12
 * @author weirx
 * @version 3.0
 */
public class NortheastDishes implements IDishes {
    private ICooker cooker;

    public NortheastDishes(ICooker cooker) {
        this.cooker = cooker;
    }

    @Override
    public void order() {
        System.out.println("顾客下单东北菜");
        cooker.doCooking();
    }

    @Override
    public void back() {
        System.out.println("顾客取消东北菜订单了");
        cooker.stopCooking();
    }
}

小二:

import java.util.ArrayList;
import java.util.List;

/**
 * 服务员
 * @date: 2021/1/12
 * @author weirx
 * @version 3.0
 */
public class Waiter {

    /**
     * 菜单
     */
    private List<IDishes> list = new ArrayList<>();

    /**
     * 顾客下单
     * @param dishes
     */
    public void order(IDishes dishes) {
        list.add(dishes);
    }

    /**
     * 顾客退单
     * @param dishes
     */
    public void back(IDishes dishes) {
        for (IDishes d : list) {
            if (d.getClass().getName().equals(d.getClass().getName())) {
                list.remove(dishes);
            }
        }
    }

    /**
     * 通知厨师下单
     */
    public void doCooking() {
        for (IDishes d : list) {
            d.order();
        }
    }

    /**
     * 通知厨师退单
     * @param dishes
     */
    public void stopCooking(IDishes dishes) {
        dishes.back();
    }

    /**
     * 查看菜单
     */
    public void searchDishesList(){
        System.out.println("当前菜单:");
        for (IDishes d : list) {
            System.out.println(d.getClass().getName());
        }
    }
}

测试类:

/**
 * 测试类
 * @date: 2021/1/12
 * @author weirx
 * @version 3.0
 */
public class TestDemo {

    public static void main(String[] args) {
        Waiter waiter = new Waiter();
        SichuanDishes sichuanDishes = new SichuanDishes(new SichuanCooker());
        NortheastDishes northeastDishes = new NortheastDishes(new NortheastCooker());
        System.out.println("--------------顾客点单----------------");
        //顾客点单
        waiter.order(sichuanDishes);
        waiter.order(northeastDishes);
        waiter.searchDishesList();
        System.out.println("---------------小二下单---------------");
        //小二下单
        waiter.doCooking();
        System.out.println("---------------顾客退单四川菜---------------");
        //顾客退单四川菜
        waiter.back(sichuanDishes);
        waiter.stopCooking(sichuanDishes);
        waiter.searchDishesList();
        System.out.println("------------------------------");
    }
}

4、分析

厨师 菜品 小二

如上所示,在创建菜品时,需要指定厨师接口ICooker作为构造参数。而小二下单和通知厨师时,都是传递的菜品接口IDishes作为参数,符合命令模式。

5、总结

优点:
1)单一职责原则。
2)开闭原则。
3)你可以实现撤销和恢复功能。
4)你可以实现操作的延迟执行。
5)你可以将一组简单命令组合成一个复杂命令。
缺点:
1)代码变得复杂

相关文章

网友评论

    本文标题:设计模式(十五)命令模式

    本文链接:https://www.haomeiwen.com/subject/figloktx.html