设计模式-------命令模式
重点中的重点: 把"执行者"类当中的方法变成多个命令类,这个步骤是把多个完全不同的方法变成一个统一接口,这样可以让命令接收者不用关注类中方法细节。。。厉害,把一个类中方法给统一命名啦。。。我认为命令模式的精髓在于:增加了一个命令的管理者,为了使管理者管理命令更加方便,我们使用适配器模式统一了所有命令的接口,因为有List来接受命令,所以可以有命令队列,因为有remove();所以可以撤销命令,因为有add()我们还可以在执行的过程中动态的增加命令。。。这是他的好处,其实他与策略完全不同/**语义: 一个MM要命令你做事情,但是命令是不能写死的,说不定哪天他就又命令你做些新的事情。。。技术: 既然mm命令的方法是变化的,不定的,是mm想出来的所以由mm来new 出来,然后设置给boy....接受命令的人一定是执行命令的人你是Client ,按键是Invoker,mp3是Receiver,播放就是一个命令Command对象,那么谁来真正执行这个命令呢? 哈哈,命令的执行者被隐藏在了Command的背后哈,被Command封装了起来----命令模式的精髓---命令的执行者被隐藏在命令的背后,与发号施令的人无关*/public interface command{ //这里的执行者是临时实现的,实现了execute的都是执行者(Receiver) public void execute();}public class MM{ public void order(Boy b){Command c = new ShoppingCommand(); //注意:制造命令的人不是仅仅造出了命令,而且造出了命名的执行,其实这里mm把自己造出的命名给定义了如何执行,boy只是去按照他的方法执行而已。。。如果传递的是字符串,当然达不到这个效果,因为字符串并没有传递命令的执行本身。。。。b.add(c);b.execute();}}public class Boy { //Invoker,他是命令的请求方,如果不用命令模式,那么Boy就是命令的执行方,private String name; //boy可以接受好多命令哦~~~~List<Command> commands = new ArrayList<Command>();public void add(Command c){commands.add(c);}public String getName() {return name;}public void setName(String name) {this.name = name;}public void execute() {for(Command c:commands){c.execute();}}}如果Invoker像下面这样,那么可以不需要,其实Invoker存在的意义我认为:1.管理链式接口2.有某种物理含义,比如上面的Boypublic class Invoker{ private Command command; public void setCommand(Command command){ this.command = command; } public void action(){ this.command.execute(); }}/*注意:扩展接口有两种方式1.第一种,就是让那个类实现某个接口比如: Master impelnets Hearable2.搞一个新的类来实现,这个和语意有关,从语文角度看。。。一个人能做什么,那么扩展接口,如果一个类被动接收命令,那么让命令来封装持有这个类的引用。。。。*/public class LightOnCommand implements Command{ //命令模式中命令的执行者 Light light; public LightOnCommand(){ this.light = light; } public void execute(){ //这里就是为了统一接口,让调用者不知节 light.on(); }}//第二种做法的好处很明显,因为我不用去修改light这个类了,只需要把light包装一下,哈哈对修改关闭,对扩展开放就很明显了。。。。//命令模式的扩展-----"Party"模式,所谓Party模式就是一票的命令的集合而已啦//Java中的命令模式,如Scheduler,线程池,工作队列,想象一下你在某端添加命令,然后在另一端则是线程,线程进行下面的动作:从队列中取出一个命令,然后调用它的exectue()方法,等待这个调用完成,然后讲此命令对象丢弃,再取下一个命令。。。线程池在这里相当于Invoker,是命令的请求方,相当于Boy..........我们可以把Invoker看成是客户代理,对真正的客户来说屏蔽了细节命令的执行者被隐藏在命令的背后,与发号施令的人无关还有这样的Commandpublic abstract class Command{ protected RequirementGroup rg = new RequirementGroup(); protected PageGroup rg = new PagetGroup(); protected CodeGroup rg = new CodeGroup(); public abstract void execute();}public class DeletePageCommand extends Command{ public void execute(){ super.rg.find(); super.rg.delete(); super.rg.plan(); }}-------------------例子二:烤羊肉串-------------------------去买羊肉串,我给钱给大叔,大叔烤羊肉串,然后再给我们。。。。但有时我们却感到烤羊肉串的人经常找错钱什么的。。。这其实就是"行为请求者"与"行为实现者"的紧耦合。我们需要记录那些人要几串羊肉串,有没有特殊要求,付没付钱,谁先谁后,这其实都相当于请求做什么...对请求做记录,应该是日志,对于有人要退回请求或者要烤肉重烤,这相当于撤销和重做,所以对请求队列或者记录请求日志以及支持可撤销的操作时,请求者与行为是闲着的紧耦合是不太合适的。。。而开店就是实现了行为请求者和行为实现者之间的解耦。。。因为服务员是这个中间层。。。服务员根据客户需要发个命令就可以了,我们的做法是把"烤肉串这"类中地方,分别写成多个命令类,那么他们就可以被"服务员"来请求了//抽象命令类,只需要确定"烤肉串师傅"是谁,可以看成是菜单哈public abstract class Command{ protected Barbecuer receiver; public Command(Barbecuer receiver){ this.receiver = receiver; } abstract public void execute();}//烤肉串命令class BakeMuttonCommand extends Command{ public void execute(){ receiver.BakeMutton(); }}//烤鸡翅命令class BakeChickenWingCommand extends Command{ public void execute(){ receiver.BakeChickenWing(); }}//服务员类,负责接收命令,发送命令public class Waiter{ //private Command command; private List<Command> commands = new ArrayList<Command>(); public void setOrder(Command command){ // this.command = command; if("没有菜了")"请点别的菜哈"; else commands.add(command); } //通知执行 public void notifyBabecuer(){ for(Command c : commands){ c.execute(); } //取消订单 public void cancelOrder(Command command){ commands.remove(command); }}命令模式将一个请求封装成一个对象,从而使你可以用不同的请求对客户端进行参数化,对请求排队或记录请求日志以及支持可撤销的操作。