尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

【设计模式】-命令模式学习(一)

【设计模式】-命令模式学习(一) 目录背景我的场景类图设计代码实现运行结果解读1、服务员类2、命令类对服务员手上的“小册子”的抽象记录点餐要求支持用户撤销。3、厨师类具体执行类不同类型的厨师做不同的菜减少厨师切换成本4、 客户端代表用户发来请求用户只说自己需要什么不需要知道烤串、炒菜谁来做。总结1、什么是命令模式2、梳理需求——确定类——画类图——根据类图写代码。3、代码如人生遗留问题命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作[DP]。背景最近在学习设计模式-命令模式参考 《大话设计模式》里面讲到了小菜和大鸟吃烧烤的故事他们先去了烧烤摊烧烤摊接待客户和烤串者都是同一个人问题频出烤错了、烤少、结错账……于是他们转战到烧烤店烧烤店服务员接待他们用“小册子”记录他们点餐错了还能划掉最后顺利吃烤串账单正确。原文如下我心想我也爱吃烧烤把我自己吃烧烤的经验用命令模式实现一遍让我的生活融入代码吧说干就干我的场景来到某烧烤店我“服务员来两串牛肉串两串羊肉串一个炒方便面... ...”。服务员在“小册子”上写下”牛肉串✖️2羊肉串✖️2炒方便面 ✖️1 ... ...”。服务员去后厨给炒菜师傅炒菜菜单通知烤串师傅烤串菜单。类图设计代码实现import java.util.ArrayList; import java.util.List; public class Waiter { // 维护命令列表,聚合关系 private ListCommand commands new ArrayList(); // 添加命令 // 服务员根据 name 和 number 创建 command根据 name区分烤串还是炒菜根据 number区分是几道菜创建 command public void addCommand(String name,int number) { if(name.contains(烤)){ commands.add(new BakeCommand(name,number,new BakeCook())); }else { commands.add(new FryCommand(name,number,new FryCook())); } } public void notifyExecute() { System.out.println(开始通知后厨); for (Command command : commands) { command.execute(); }public abstract class Command { private String name; // 菜名 private int number; // 数量 private Cook cook; // 厨师 // 构造方法 - Command 聚合 Cook // 创建 command 的时候服务员把厨师聚合进来服务员知道什么类型的菜交给什么厨师做 public Command(String name, int number, Cook cook){ this.name name; this.number number; this.cook cook; } public String getName() { return name; } public int getNumber() { return number; } public void execute(){ cook.bake(this); } }public class BakeCommand extends Command{ public BakeCommand(String name, int number, Cook cook){ super(name, number, cook); } }public class FryCommand extends Command { public FryCommand(String name, int number, Cook cook) { super(name, number, cook); } }public interface Cook { public void bake(Command command); }public class BakeCook implements Cook{ Override public void bake(Command command) { System.out.println([烧烤厨房] command.getNumber() 个 command.getName() 开始烤啦!); } }public class FryCook implements Cook{ Override public void bake(Command command) { System.out.println([炒菜厨房] command.getNumber() 个 command.getName() 开始做啦!); } }public class Client { public static void main(String[] args) { // 来了一个顾客开始下单 System.out.println(顾客开始下单); Waiter waiter new Waiter(); waiter.addCommand(烤羊肉串,2); waiter.addCommand(烤牛肉串,2); waiter.addCommand(烤油边,2); waiter.addCommand(炒方便面,1); waiter.addCommand(田园大拌菜,1); waiter.notifyExecute(); } }运行结果顾客开始下单 开始通知后厨 [烧烤厨房]2个烤羊肉串 开始烤啦! [烧烤厨房]2个烤牛肉串 开始烤啦! [烧烤厨房]2个烤油边 开始烤啦! [炒菜厨房]1个炒方便面 开始做啦! [炒菜厨房]1个田园大拌菜 开始做啦!解读1、服务员类1维护命令列表private List commands new ArrayList();2接受订单3维护“映射”, 按菜品名查表创建 Command 知道烤串和炒菜分别让哪个师傅做因此服务员持有对 BakeCook 和 FryCook的引用4撤销订单5将客户与厨师解耦6通知厨师制作2、命令类对服务员手上的“小册子”的抽象记录点餐要求支持用户撤销。用多态区分不同命令类型。3、厨师类具体执行类不同类型的厨师做不同的菜减少厨师切换成本1做饭4、 客户端代表用户发来请求用户只说自己需要什么不需要知道烤串、炒菜谁来做。总结1、什么是命令模式自己写完实现后内心产生了疑惑到底什么是命令模式关键代码是什么某天听米老师讲完面向对象后我懂了命令模式就是将请求封装成对象去处理。我兴高采烈的向米老师求证老师肯定了我的答案并抛出了另一个问题为什么这样做只知道结论不行我再次陷入沉思。2、梳理需求——确定类——画类图——根据类图写代码。早在 10 年前米老师就教我正确的开发顺序直到这次才算清清楚楚实现认真思考了每个类的生命周期。3、代码如人生为什么我决定自己实现一遍命令模式呢因为第一遍看完书我觉得书上写的不对。客户端怎么能知道哪个厨师去执行命令呢我去吃烧烤从不关注哪个厨师做饭应该是服务员关注啊。于是在我设计的类图中client 只知道 waiter其他什么都不知道由waiter 依赖 cook解决哪个菜由谁做的问题。但我想能写出这么好的书的作者这么写一定有他的道理道理是什么呢终于实现完自己的设计后我想明白了我可以知道哪个厨师在做饭或者说我可以指定厨师。比如一个烧烤店老板和厨师都是同一个人那我就知道是谁做饭了或者说小王师傅的腌笃鲜一绝目前在某五星大饭店任职你去饭店说我要吃小王师傅做的腌笃鲜。对应到代码是什么呢就是调用方指定某个类去执行对应的业务。遗留问题1、waiter还是单一职责的服务员吗2、服务员把“烤”写错了烤串还能吃上吗我们留在下一篇博客中分析。
返回列表