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)代码变得复杂
网友评论