命令模式
一. 说明
命令模式将请求包装成对象,传递给调用者,调用者寻找可以处理该命令的合适的对象,该对象可以对请求排队或记录请求日志,以及可以修改和撤销的操作。命令模式是行为型模式的一种。
从字面上看命令模式的解释,比较不容易接受,它在我们平常开发中并不常见和常用,但是生活中我们可以经常看到这样的例子,比如我们在写代码时用到的ctrl+c和ctrl+v,它们就是一种命令,我们通过键盘快捷键,将操作指令传递给计算机系统实现文本赋值和粘贴。
二.应用场景
- 菜单和按钮的点击事件,触发时通过命令模式将数据封装成对象,传递给接收者执行对应操作
- 命令模式可以很方便的实现撤销和重做功能,它将命令保存到历史记录中,我们随时可以对记录做修改删除等操作。
- 事务操作中,在开启事务时可以创建一个命令对象,后续所有的数据库操作都保存在命令对象中,最终提交事务或回滚事务撤销操作。
三.代码示例
我们以餐厅里的菜系为例演示命令模式,餐厅里有川菜、粤菜两大菜品,对应有川菜大厨、粤菜大厨两个师傅,顾客点哪种菜则对应哪个师傅来做,顾客只需要通知给服务员,由服务员传达给后厨。
这里一种菜品其实就是一个命令,命令的执行者就是各种大厨,我们需要将每一种菜品都设定好对应的大厨,即每一种命令设定好对应的执行者。
先创建菜品接口(命令)和厨师接口(执行者)
public interface IFood {
//菜品制作
void cook();
}
public interface ICook {
//厨师烹饪
void cooking();
}
再创建菜品的两个实现类:川菜、粤菜, 厨师的两个实现类:川菜大厨、粤菜大厨
public class SiChuanFood implements IFood {
private ICook cook;
public SiChuanFood(ICook cook) {
this.cook = cook;
}
@Override
public void cook() {
cook.cooking();
}
}
public class GuangDongFood implements IFood {
private ICook cook;
public GuangDongFood(ICook cook) {
this.cook = cook;
}
@Override
public void cook() {
cook.cooking();
}
}
public class SiChuanCook implements ICook {
@Override
public void cooking() {
System.out.println("烹饪川菜");
}
}
public class GuangDongCook implements ICook{
@Override
public void cooking() {
System.out.println("烹饪粤菜");
}
}
最后编写服务员类
public class Waiter {
private List<IFood> foods = new ArrayList<>();
/**
* 下单菜品
*/
public void order(IFood food){
foods.add(food);
}
/**
* 提交所有菜品
*/
public void submitFoods(){
foods.forEach(food -> food.cook());
foods.clear();
}
}
编写测试代码
public static void main(String[] args) {
SiChuanFood sFood = new SiChuanFood(new SiChuanCook());
GuangDongFood gFood = new GuangDongFood(new GuangDongCook());
Waiter waiter = new Waiter();
waiter.order(sFood);
waiter.order(sFood);
waiter.order(sFood);
waiter.order(gFood);
waiter.order(sFood);
waiter.submitFoods();
}
四. 总结
总之,命令模式适用于需要将请求封装成对象,并根据需要进行排队、延迟、撤销和日志记录等操作的场景。通过命令模式,可以使请求发送者和接收者解耦,提高系统的灵活性和可扩展性。