命令模式在我们通常的互联网开发中相对来说用的比较少,但这样的模式在我们的日常中却经常使用到,那就是Ctrl+C、Ctrl+V。当然如果你开发过一些桌面应用,也会感受到这样设计模式的应用场景。从这样的模式感受上,可以想到这是把逻辑实现与操作请求进行分离,降低耦合方便扩展。
命令模式是行为模式中的一种,以数据驱动的方式将命令对象,可以使用构造函数的方式传递给调用者。调用者再提供相应的实现为命令执行提供操作方法。可能会感觉这部分有一些饶,可以通过对代码的实现进行理解,在通过实操来熟练。
在这个设计模式的实现过程中有如下几个比较重要的点;
在这个案例中我们模拟在餐厅中点餐交给厨师烹饪的场景
命令场景的核心的逻辑是调用方与不需要去关心具体的逻辑实现,在这个场景中也就是点餐人员只需要把需要点的各种菜系交个小二就可以,小二再把各项菜品交给各个厨师进行烹饪。也就是点餐人员不需要跟各个厨师交流,只需要在统一的环境里下达命令就可以。
在这个场景中可以看到有不同的菜品;山东(鲁菜)、四川(川菜)、江苏(苏菜)、广东(粤菜)、福建(闽菜)、浙江(浙菜)、湖南(湘菜),每种菜品都会有不同的厨师进行烹饪。而客户并不会去关心具体是谁烹饪,厨师也不会去关心谁点的餐。客户只关心早点上菜,厨师只关心还有多少个菜要做。而这中间的衔接的过程,由小二完成。
那么在这样的一个模拟场景下,可以先思考哪部分是命令模式的拆解,哪部分是命令的调用者以及命令的实现逻辑。
不考虑设计模式的情况下,在做这样一个点单系统,有一个类就够了
像是这样一个复杂的场景,如果不知道设计模式直接开发,也是可以达到目的的。但对于后续的各项的菜品扩展、厨师实现以及如何调用上会变得非常耦合难以扩展。
itstack-demo-design-14-01└──src└──main└──java└──org.itstack.demo.design└──XiaoEr.java2.代码实现publicclassXiaoEr{privateLoggerlogger=LoggerFactory.getLogger(XiaoEr.class);privateMap
命令模式可以将上述的模式拆解三层大块,命令、命令实现者、命令的调用者,当有新的菜品或者厨师扩充时候就可以在指定的类结构下进行实现添加即可,外部的调用也会非常的容易扩展。
itstack-demo-design-14-02└──src├──main│└──java│└──org.itstack.demo.design│├──cook││ ├──impl││ │├──GuangDongCook.java││ │├──JiangSuCook.java││ │├──ShanDongCook.java││ │└──SiChuanCook.java││ └──ICook.java│├──cuisine││ ├──impl││ │├──GuangDoneCuisine.java││ │├──JiangSuCuisine.java││ │├──ShanDongCuisine.java││ │└──SiChuanCuisine.java││ └──ICuisine.java│└──XiaoEr.java└──test└──java└──org.itstack.demo.test└──ApiTest.java命令模式模型结构
publicclassGuangDoneCuisineimplementsICuisine{privateICookcook;publicGuangDoneCuisine(ICookcook){this.cook=cook;}publicvoidcook(){cook.doCooking();}}江苏(苏菜)
publicclassJiangSuCuisineimplementsICuisine{privateICookcook;publicJiangSuCuisine(ICookcook){this.cook=cook;}publicvoidcook(){cook.doCooking();}}山东(鲁菜)
publicclassShanDongCuisineimplementsICuisine{privateICookcook;publicShanDongCuisine(ICookcook){this.cook=cook;}publicvoidcook(){cook.doCooking();}}四川(川菜)
publicclassSiChuanCuisineimplementsICuisine{privateICookcook;publicSiChuanCuisine(ICookcook){this.cook=cook;}publicvoidcook(){cook.doCooking();}}2.3抽象实现者定义(厨师接口)publicinterfaceICook{voiddoCooking();}2.4实现者具体实现(四类厨师)粤菜,厨师
publicclassGuangDongCookimplementsICook{privateLoggerlogger=LoggerFactory.getLogger(ICook.class);publicvoiddoCooking(){logger.info("广东厨师,烹饪鲁菜,宫廷最大菜系,以孔府风味为龙头");}}苏菜,厨师
publicclassJiangSuCookimplementsICook{privateLoggerlogger=LoggerFactory.getLogger(ICook.class);publicvoiddoCooking(){logger.info("江苏厨师,烹饪苏菜,宫廷第二大菜系,古今国宴上最受人欢迎的菜系。");}}鲁菜,厨师
publicclassShanDongCookimplementsICook{privateLoggerlogger=LoggerFactory.getLogger(ICook.class);publicvoiddoCooking(){logger.info("山东厨师,烹饪鲁菜,宫廷最大菜系,以孔府风味为龙头");}}