命令模式定义:将一个请求封装为一个对象,从而使你不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作
下面给个例子,是模拟对电视机的操作有开机、关机、换台命令。代码如下
//命令接收者
public class Tv {
public int currentChannel = 0;
public void turnOn() {
System.out.println("The televisino is on.");
}
public void turnOff() {
System.out.println("The television is off.");
}
public void changeChannel(int channel) {
this.currentChannel = channel;
System.out.println("Now TV channel is " + channel);
}
}
//执行命令的接口
public interface Command {
void execute();
}
//开机命令
public class CommandOn implements Command {
private Tv myTv;
public CommandOn(Tv tv) {
myTv = tv;
}
public void execute() {
myTv.turnOn();
}
}
//关机命令
public class CommandOff implements Command {
private Tv myTv;
public CommandOff(Tv tv) {
myTv = tv;
}
public void execute() {
myTv.turnOff();
}
}
//频道切换命令
public class CommandChange implements Command {
private Tv myTv;
private int channel;
public CommandChange(Tv tv, int channel) {
myTv = tv;
this.channel = channel;
}
public void execute() {
myTv.changeChannel(channel);
}
}
//可以看作是遥控器吧
public class Control {
private Command onCommand, offCommand, changeChannel;
public Control(Command on, Command off, Command channel) {
onCommand = on;
offCommand = off;
changeChannel = channel;
}
public void turnOn() {
onCommand.execute();
}
public void turnOff() {
offCommand.execute();
}
public void changeChannel() {
changeChannel.execute();
}
}
//测试类
public class Client {
public static void main(String[] args) {
// 命令接收者
Tv myTv = new Tv();
// 开机命令
CommandOn on = new CommandOn(myTv);
// 关机命令
CommandOff off = new CommandOff(myTv);
// 频道切换命令
CommandChange channel = new CommandChange(myTv, 2);
// 命令控制对象
Control control = new Control(on, off, channel);
// 开机
control.turnOn();
// 切换频道
control.changeChannel();
// 关机
control.turnOff();
}
}
执行结果为:
The televisino is on.
Now TV channel is 2
The television is off.
转载自http://hi.baidu.com/%D0%D0%D7%DF%D4%DA%BF%D5%D6%D0/blog/item/6f4d03c48dab4aa38326ac2a.html
另一种实现
具体的Command模式代码各式各样,因为如何封装命令,不同系统,有不同的做法.下面事例是将命令封装在一个Collection的List中,任何对象一旦加入List中,实际上装入了一个封闭的黑盒中,对象的特性消失了,只有取出时,才有可能模糊的分辨出:
package com;
/**
* 典型的Command模式需要有一个接口.
* 接口中有一个统一的方法,这就是"将命令/请求封装为对象
* @author Administrator
*
*/
public interface Command {
public void execute();
}
package com;
/**
* 具体不同命令/请求代码是实现接口Command,
* @author Administrator
*
*/
public class Engineer implements Command {
@Override
public void execute() {
// TODO Auto-generated method stub
System.out.println("工程师的建议");
}
}
package com;
public class Programmer implements Command {
@Override
public void execute() {
// TODO Auto-generated method stub
System.out.println("程序员的建议");
}
}
package com;
public class Politician implements Command {
@Override
public void execute() {
// TODO Auto-generated method stub
System.out.println("政客的建议");
}
}
package com;
import java.util.ArrayList;
import java.util.List;
/**
* 按照通常做法,我们就可以直接调用这三个Command,
* 但是使用Command模式,我们要将他们封装起来,扔到黑盒子List里去
* @author Administrator
*
*/
public class Producer {
/**
* 这三个命令进入List中后,已经失去了其外表特征,
* 以后再取出,也可能无法分辨出谁是Engineer 谁是Programmer了,看下面客户端如何调用Command模式:
* @return
*/
public static List<Command> produceRequest(){
List<Command> commands = new ArrayList<Command>();
commands.add(new Engineer());
commands.add(new Programmer());
commands.add(new Politician());
return commands;
}
}
package com;
import java.util.Iterator;
import java.util.List;
public class Client {
public static void main(String[] args) {
List<Command> commands = Producer.produceRequest();
for(Iterator<Command> it = commands.iterator();it.hasNext();){
客户端直接调用execute方法,无需知道被调用者的其它更多类的方法名。
it.next().execute();
}
}
}
//由此可见,调用者基本只和接口打交道,不合具体实现交互,这也体现了一个原则,面向接口编程,这样,以后增加第四个具体命令时,就不必修改调用者TestCommand中的代码了.