多平台统一管理软件接口,如何实现多平台统一管理软件接口
222
2022-10-30
从饭店聊命令模式
诸位看官,请将下面的事例转换成代码.
"我去餐厅吃饭,点了一碗面条,三只鸡翅"
怎么样,够简单的吧,知道你们都比较懒,不想编码,看看下面这个是不是和你想的一样
package com.command; public class NoodlesReceiver { String name; public NoodlesReceiver(String name){ this.name=name; } @Override public void doSomeThing(int table_num,int food_count) { // TODO Auto-generated method stub System.out.println(name+"给"+table_num+"号桌下"+food_count+"碗面条"); }}package com.command;public class BakeChickenWingReceiver { String name; public BakeChickenWingReceiver(String name){ this.name=name; } public void doSomeThing(int table_num,int food_count) { // TODO Auto-generated method stub System.out.println(name+"给"+table_num+"号桌来"+food_count+"个烤鸡翅"); }}package com.command;public class client { public static void main(String[] args) { //初始化两个厨师 NoodlesReceiver noodlesReceiver= new NoodlesReceiver("下面条的李师傅"); BakeChickenWingReceiver bakeChickenWingReceiver= new BakeChickenWingReceiver("烤鸡翅的张师傅"); noodlesReceiver.doSomeThing(10, 1); bakeChickenWingReceiver.doSomeThing(10, 3); }}
结果如下
下面条的李师傅给10号桌下1碗面条
烤鸡翅的张师傅给10号桌来3个烤鸡翅
怎么样,和你想的一样吗?
可是看上面的例子,如果再返回现实,那就是你去了饭店,直接对烤肉师傅和面条师傅下命令!开玩笑,咱都是有身份证的人,能亲自跑到满是油烟的厨房去?咋能没有服务员呢?(况且从软件设计的角度来讲,命令的发出者与实行者最好解耦).
第一次重构
两个厨师不变.加一个服务员.
package com.command;public class Waiter2 { NoodlesReceiver noodlesReceiver; BakeChickenWingReceiver bakeChickenWingReceiver; String name; public Waiter2(String name){ this.name=name; //初始化两个厨师 一个服务员 noodlesReceiver=new NoodlesReceiver("下面条的李师傅"); bakeChickenWingReceiver=new BakeChickenWingReceiver("烤鸡翅的张师傅"); } public void order(int table_num,int food_count,String food){ switch (food) { case "鸡翅": bakeChickenWingReceiver.doSomeThing(table_num, food_count); break; case "面条": noodlesReceiver.doSomeThing(table_num, food_count); break; default: System.out.println("sorry 小店没有您要点的食物"); break; } }}package com.command;public class client2 { public static void main(String[] args) { Waiter2 waiter2=new Waiter2("小美"); waiter2.order(10, 1, "面条"); waiter2.order(10, 3, "鸡翅"); waiter2.order(10, 3, "馒头"); }}
结果如下:
下面条的李师傅给10号桌下1碗面条
烤鸡翅的张师傅给10号桌来3个烤鸡翅
sorry 小店没有您要点的食物
看看client2 似乎还蛮不错的,给服务员说几号桌子点什么东西点几份,都很好呀,很符合实际.嗯,确实和很符合实际.问题是
1:大家看看服务员的类.服务员类里面包含两个厨师类,咱们暂且不论如果以后厨师发生变动,还需要改服务员的类,就是现实世界中也不不是这样呀!现实世界是:服务员是服务员,厨师是厨师,这俩没关系!
2:你去饭店吃饭,你是点完一个菜,就让服务员通知一次厨师?你要敢这样,服务员肯定心里骂你:nnd,你丫能不能一次说完,让我少跑几趟.
3:我刚点完1碗面条就不能更改了,我后悔了不想吃了,都不行.这也不符合实际.只有你的面条还没下锅,我就能取消.
我得告诉大家这次重构很遗憾,失败了!那咋办?回想实际情况.
实际情况并不是服务员给厨师下命令,也不是你点一道菜服务员就跑一次.而是服务员带着要给小本,上面可以写一条条的命令.等你点了十道八道菜后,有后悔了,推掉两道菜后,说ok了,服务员才将命令整体发送.对吧,实际难道不是这样?
命令,命令!!! 在这个问题里,命令是根本.各位看官请注意,不要钻牛角尖,大家可以这样想,这里的命令不是动词,不是人的一个方法,而是名词,是你写出来的一个"实体".且命令中包含接受命令的人.简单的说,命令本身知道,自己要传递给谁.(万物皆对象,且都有自己的属性,方法)
第二次重构
2.1次重构.
既然现在有两种厨师,那就先设置两种命令.而且要知道自己是传递给谁的,为了统一,给那两个厨师都加要给父类(接口).
public interface IReceiver { public void doSomeThing(int table_num,int food_count);}
让两个厨师都实现IReceiver.代码不再赘述.
同理我们得让两个命令也都有个父类(接口).
package com.command;public interface ICommand { public void action();}package com.command;public class BakeChickenWingCommand implements ICommand{ int count; int num; IReceiver receiver; public BakeChickenWingCommand(IReceiver receive,int count,int num){ this.receiver=receive; this.count=count; this.num=num; } @Override public void action() { // TODO Auto-generated method stub receiver.doSomeThing(num, count); }}
面条的命令不再赘述,和鸡翅基本一样,不对,我看看,我擦 完全一样!
咋办?既然都一样,按就不分父类子类了,直接就是下面的样子
2.2次重构
public class Command { int count; int num; IReceiver receiver; public Command(IReceiver receive,int count,int num){ this.receiver=receive; this.count=count; this.num=num; } public void action() { // TODO Auto-generated method stub receiver.doSomeThing(num, count); }}
诸位看官以为如何. 别着急发表意见 想想再说.先看看命令模式的类图.
(上图来自<<大话设计模式>>) 其实在去饭店吃饭的例子里,是可以的,因为不管厨师是做面条还是鸡翅,都可以用一个doSomeThing来代替.可换一个场景呢?古代皇帝,让臣下打仗,镇守地方,升官,贬职你还都用一个doSomeThing搞定吗?所以必须分层必须用接口.
所以很遗憾,2.2次重构又失败了.但是就像哪个谁谁谁说的"没有经历过苦痛的顿悟是轻佻的",我们只有错过很多次才能真正的"对".
2.3次重构
越过上面的岔路,下面就是服务员了,刚才已经说了,服务员至少得提升两点,一能存储命令,打包发送,二就是能在提交所以命令前,撤销一部分命令,代码如下
package com.command;import java.util.ArrayList;public class Waiter { String name; ArrayList 再来看看客户端的调用 package com.command;public class Client { public static void main(String[] args) { //初始化两个厨师 一个服务员(可以理解为饭店聘请了这三个人) NoodlesReceiver noodlesReceiver= new NoodlesReceiver("下面条的李师傅"); BakeChickenWingReceiver bakeChickenWingReceiver= new BakeChickenWingReceiver("烤鸡翅的张师傅"); Waiter waiter=new Waiter("小美"); //顾客发出三个命令 NoodelsCommand noodelsCommand1= new NoodelsCommand(noodlesReceiver, 6, 3); NoodelsCommand noodelsCommand2= new NoodelsCommand(noodlesReceiver, 30, 2); BakeChickenWingCommand bakeChickenWingCommand= new BakeChickenWingCommand(bakeChickenWingReceiver, 4, 8); //服务员记录三个命令后 又撤销一个 waiter.addCommand(noodelsCommand1); waiter.addCommand(noodelsCommand2); waiter.addCommand(bakeChickenWingCommand); waiter.removeCommand(noodelsCommand2); //服务员将菜单上交 厨师做菜 waiter.submit(); }} 结果如下 顾客取消订单 下面条的李师傅给3号桌下6碗面条 烤鸡翅的张师傅给8号桌来4个烤鸡翅 好了大功告成 现在总结一下命令模式的好处 1:它实现了命令队列; 2:把命令看成一个个实体,使得每做一次命令都能记下日志; 3:命令可撤销 这一点在某些有这样需求的系统中很有用; 4:也是最重要的一点 它让一个任务的请求者和实现者分离; 5:新加入的命令只要实现ICommand接口就好,方便扩展. 另外,本人的一点心得,设计模式有很多问题,例如因为xxx所以xxx,在初学者看来是很模糊的,为什么?这个所以和因为有关系吗?遇到这个问题,只能说内力还不够,继续编码吧.
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~