第二十五讲:命令模式
package com.ibeifeng.ex1; public class MainClass { public static void main(String[] args) { Peddler peddler = new Peddler(); peddler.sailApple(); peddler.sailBanana(); } }
package com.ibeifeng.ex1; //小摊,小贩 /* * 小商贩 * */ public class Peddler { //卖苹果 public void sailApple(){ System.out.println("卖苹果"); } //卖香蕉 public void sailBanana(){ System.out.println("卖香蕉"); } }
Command:Command.
Client:MainClass
对于每一个行为都创建一个Command的实现子类:AppleCommand.
//命令类必须包含调用方,是谁在卖,是Peddler在卖.所以命令类需要持有Peddler的引用.
Invorker:执行Command对象.被调用者:Peddler,商贩被调用,所以需要持有一个Peddler的引用.
实现了使用一个专门的类Command对这种调用过程加以封装.使用命令类除了可以对以前的调用加以封装还可以添加额外的功能.
package com.ibeifeng.ex2; public class AppleCommand extends Command{ public AppleCommand(Peddler peddler) { super(peddler); // TODO Auto-generated constructor stub } @Override public void sail() { // TODO Auto-generated method stub //this.peddler.sailApple(); this.getPeddler().sailApple();//不管你怎么搞,还是商贩在卖. } }
package com.ibeifeng.ex2; public class BananaCommand extends Command{ public BananaCommand(Peddler peddler) { super(peddler); // TODO Auto-generated constructor stub } @Override public void sail() { // TODO Auto-generated method stub this.getPeddler().sailBanana(); } }
package com.ibeifeng.ex2; public abstract class Command { private Peddler peddler; //protected Peddler peddler;//子类如果要直接访问peddler可以改成保护类型. //不必隐藏细节隐藏的那么深.并不是每个属性都是private.你只是去考虑访问权限就行了. public Command(Peddler peddler) {//提供一个构造函数比较方便. //将构造函数放在最上面,这也是我们平常的一个习惯. super(); this.peddler = peddler; } public abstract void sail(); //命令类必须包含调用方,是谁在卖,是Peddler在卖.所以命令类需要持有Peddler的引用. public Peddler getPeddler() { return peddler; } public void setPeddler(Peddler peddler) { this.peddler = peddler; } }
package com.ibeifeng.ex2; public class MainClass { public static void main(String[] args) { Peddler peddler = new Peddler(); /*peddler.sailApple(); peddler.sailBanana();*/ Command appleCommand = new AppleCommand(peddler); Command bananaCommand = new BananaCommand(peddler); appleCommand.sail(); bananaCommand.sail();//通过不同的命令来调用它的sail()方法 } }
package com.ibeifeng.ex2; //小摊,小贩 /* * 小商贩 * */ public class Peddler { //卖苹果 public void sailApple(){ System.out.println("卖苹果"); } //卖香蕉 public void sailBanana(){ System.out.println("卖香蕉"); } }
希望有一个类Receiver.小商贩赚了一些钱了,不想自己动手了,他可以请一个服务员:waiter.帮手.
Receiver:Receiver(waiter)里面有action()方法,其实action()方法是执行Command的方法.Receiver接受一个命令.
方案二是通过命令Command的实现类调用sail()方法.所以方案三现在是由waiter来执行一个命令.所以方案三是客户跟你请的服务员直接打交道,给他发出一个命令.
package com.ibeifeng.ex3; public class AppleCommand extends Command{ public AppleCommand(Peddler peddler) { super(peddler); // TODO Auto-generated constructor stub } @Override public void sail() { // TODO Auto-generated method stub //this.peddler.sailApple(); this.getPeddler().sailApple();//不管你怎么搞,还是商贩在卖. } }
package com.ibeifeng.ex3; public class BananaCommand extends Command{ public BananaCommand(Peddler peddler) { super(peddler); // TODO Auto-generated constructor stub } @Override public void sail() { // TODO Auto-generated method stub this.getPeddler().sailBanana(); } }
package com.ibeifeng.ex3; public abstract class Command { private Peddler peddler; //protected Peddler peddler;//子类如果要直接访问peddler可以改成保护类型. //不必隐藏细节隐藏的那么深.并不是每个属性都是private.你只是去考虑访问权限就行了. public Command(Peddler peddler) {//提供一个构造函数比较方便. //将构造函数放在最上面,这也是我们平常的一个习惯. super(); this.peddler = peddler; } public abstract void sail(); //命令类必须包含调用方,是谁在卖,是Peddler在卖.所以命令类需要持有Peddler的引用. public Peddler getPeddler() { return peddler; } public void setPeddler(Peddler peddler) { this.peddler = peddler; } }
package com.ibeifeng.ex3; //小摊,小贩 /* * 小商贩 * */ public class Peddler { //卖苹果 public void sailApple(){ System.out.println("卖苹果"); } //卖香蕉 public void sailBanana(){ System.out.println("卖香蕉"); } }
package com.ibeifeng.ex3; public class Waiter { private Command command; public Command getCommand() { return command; } public void setCommand(Command command) { this.command = command; } public Waiter(Command command) { super(); this.command = command; } public Waiter() { super(); // TODO Auto-generated constructor stub } public void sail(){//服务员也有一个sail(),服务员也是在卖东西,是你的帮手 command.sail(); } }
package com.ibeifeng.ex3; public class MainClass { public static void main(String[] args) { Peddler peddler = new Peddler();//首先要有peddler,你要买的这个商贩/货家 /*peddler.sailApple(); peddler.sailBanana();*/ Command appleCommand = new AppleCommand(peddler);//实例化Command的时候把被调用方peddler传进去 //实际上操作的是商贩这个对象. Command bananaCommand = new BananaCommand(peddler); //appleCommand.sail(); //bananaCommand.sail();//通过不同的命令来调用它的sail()方法 Waiter waiter = new Waiter();//命令是由invoker(waiter)发出来的,是由它来执行这个命令. waiter.setCommand(appleCommand); waiter.sail(); waiter.setCommand(bananaCommand); waiter.sail(); } }
Client是直接和Receiver(waiter).waiter持有了command的引用.前面讲错了,
invoker:waiter,调用者,它持有了command的引用.
Receiver:被调用者,Peddler.
调用ConcreteCommand(AppleCommand、BananaCommand)的execute()方法其实是调用了Receiver(Peddler)的Action()方法.Receiver是一个目标对象.
Command:Command.调用一个行为,被调用方是谁呢?被调用方就是Receiver(Peddler).调用ConcreteCommand的execute()方法其实是执行了Receiver(Peddler)的action()方法.Command持有的是Receiver的引用.Invoker是waiter.它持有了Command的引用.
命令是发到invoker,也就是这个waiter.是由waiter来执行这个命令.
建类的顺序也是Peddler->Command->Waiter,客户端MainClass调用的顺序也是这样的一层一层.和现实生活的例子逻辑相反,客户直接和waiter交互,要买什么商家(Receiver(Peddler))的商品,发送不同的命令(比如说AppleCommand这个命令),waiter接受并执行客户的命令(比如说AppleCommand这个命令(封装了目标对象Receiver(Peddler)的行为:卖苹果),调用了AppleCommand的sail()方法,AppleCommand的sail()方法其实是调用了peddler的sailApple()方法.如果是BananaCommand这个命令,waiter就调用BananaCommand的sail()方法,调用BananaCommand的sail()方法其实是调用peddler的sailBanana()方法.
Pedder和Command可以创建在一起,但是setCommand()的时候必须把Command的实现类添加进去.
最终版的命令模式:invoker(waiter)其实是包含很多命令类,命令类是作用于Receiver(peddler)的action方法.
package com.ibeifeng.ex4; public class AppleCommand extends Command{ public AppleCommand(Peddler peddler) { super(peddler); // TODO Auto-generated constructor stub } @Override public void sail() { // TODO Auto-generated method stub //this.peddler.sailApple(); this.getPeddler().sailApple();//不管你怎么搞,还是商贩在卖. } }
package com.ibeifeng.ex4; public class BananaCommand extends Command{ public BananaCommand(Peddler peddler) { super(peddler); // TODO Auto-generated constructor stub } @Override public void sail() { // TODO Auto-generated method stub this.getPeddler().sailBanana(); } }
package com.ibeifeng.ex4; public abstract class Command { private Peddler peddler; //protected Peddler peddler;//子类如果要直接访问peddler可以改成保护类型. //不必隐藏细节隐藏的那么深.并不是每个属性都是private.你只是去考虑访问权限就行了. public Command(Peddler peddler) {//提供一个构造函数比较方便. //将构造函数放在最上面,这也是我们平常的一个习惯. super(); this.peddler = peddler; } public abstract void sail(); //命令类必须包含调用方,是谁在卖,是Peddler在卖.所以命令类需要持有Peddler的引用. public Peddler getPeddler() { return peddler; } public void setPeddler(Peddler peddler) { this.peddler = peddler; } }
package com.ibeifeng.ex4; public class MainClass { public static void main(String[] args) { Peddler peddler = new Peddler();//首先要有peddler,你要买的这个商贩/货家 /*peddler.sailApple(); peddler.sailBanana();*/ Command appleCommand = new AppleCommand(peddler);//实例化Command的时候把被调用方peddler传进去 //实际上操作的是商贩这个对象. Command bananaCommand = new BananaCommand(peddler); //appleCommand.sail(); //bananaCommand.sail();//通过不同的命令来调用它的sail()方法 Waiter waiter = new Waiter();//命令是由invoker(waiter)发出来的,是由它来执行这个命令. //waiter.setCommand(appleCommand); //下订单 waiter.setOrder(appleCommand); //waiter.sail(); //waiter.setCommand(bananaCommand); waiter.setOrder(bananaCommand); //移除订单某项 waiter.removeOrder(bananaCommand); waiter.sail(); } }
package com.ibeifeng.ex4; //小摊,小贩 /* * 小商贩 * */ public class Peddler { //卖苹果 public void sailApple(){ System.out.println("卖苹果"); } //卖香蕉 public void sailBanana(){ System.out.println("卖香蕉"); } }
package com.ibeifeng.ex4; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Waiter { //private Command command; private List<Command> commands = new ArrayList<Command>();//订单,菜单,菜谱 /*public Command getCommand() { return command; }*/ public void sail(){ for (Command command : commands){ command.sail(); } } //public void setCommand(Command command) { public void setOrder(Command command) { //this.command = command; commands.add(command); } public void removeOrder(Command command){ commands.remove(command); } /*public Waiter(Command command) { super(); this.command = command; }*/ /* public Waiter() { super(); // TODO Auto-generated constructor stub }*/ /*public void sail(){//服务员也有一个sail(),服务员也是在卖东西,是你的帮手 command.sail(); }*/ }