一个类在进行工作时会调用自己或是其他类的方法,虽然调用结果会反映在对象的状态中,但是并不会留下工作的历史纪录。
这时,如果有一个类,用来表示进行这项工作的命令就会方便很多。每一项想做的工作就不再是方法的调用这种动态处理了,而是一个表示命令的类的实例,既可以用物来表示,要想管理工作的历史纪录,只需管理这些实例的集合即可,而且还可以随时再次执行过去的命令,或是将多个过去的命令整合为一个新命令并执行。
在设计模式中,我们称这样的命令为Command模式。

示例程序
这段示例程序是一个画图软件,用户拖动鼠标时程序会绘制出红色圆点,点击clear按钮后会清除所有圆点。
用户每拖动一次鼠标,应用程序都会为“在这个位置画一个点”这条命令生成一个DrawCommand类的实例,只要保存了这条实例,以后有需要时就可以重新绘制。

设计模式(Java)—Command模式

Command接口
该接口是表示命令的接口,它的作用就是执行什么东西。

package Command;

//命令接口
public interface Command {
	//声明抽象方法
	public abstract void execute();

}

MacroCommand类
该类表示由多条命令整个成的命令,该类实现了Command接口。

package Command;

import java.util.Iterator;
import java.util.Stack;

//实现Command接口,组织多条命令
public class MacroCommand implements Command {
	private Stack<Command> commands = new Stack();
	//执行压入命令栈中的每条命令,通过迭代器调用执行方法
	@Override
	public void execute() {
		// TODO Auto-generated method stub
		Iterator iterator = commands.iterator();
		while(iterator.hasNext()){
			((Command)iterator.next()).execute();
		}
		

	}
	//如果有了新的命令,将新的命令压入栈中
	public void append(Command cmd){
		if(cmd!=this){
			commands.push(cmd);
		}
	}
	//如果撤回命令,则将命令对象pop出栈
	public void undo(){
		if(!commands.empty()){
			commands.pop();
		}
	}
	//栈清空
	public void clear(){
		commands.clear();
	}

}

DrawCommand类
该类表示绘制一个点的命令,该类的两个字段一个保存的是绘制对象,另外一个保存的是绘制位置。

package Command;

import java.awt.Point;

//执行一条命令的类
public class DrawCommand implements Command {
	//构造函数需要具体绘画类的实例和该对象在画布上的位置
	protected Drawable drawable;
	private Point position;
	public DrawCommand(Drawable drawable,Point position) {
		// TODO Auto-generated constructor stub
		this.drawable = drawable;
		this.position = position;
	}
	//执行绘制一个点的方法
	@Override
	public void execute() {
		// TODO Auto-generated method stub
		drawable.draw(position.x,position.y);

	}

}

Drawable接口
该接口是表示绘制对象的接口。

package Command;

//绘制的接口
public interface Drawable {
	public abstract void draw(int x,int y);
}

DrawCanvas类
该类实现了Drawable接口。

package Command;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;

//绘制画布和绘制点的类
public class DrawCanvas extends Canvas implements Drawable {
	private Color color = Color.red;
	private int radius = 6;
	private MacroCommand history;
	//构造函数绘制画布
	public DrawCanvas(int width,int height,MacroCommand history) {
		// TODO Auto-generated constructor stub
		setSize(width,height);
		setBackground(Color.white);
		this.history = history;
	}
	//该方法绘制一个点,包括创建画笔实例,设置画笔颜色,以及最终的画圆
	@Override
	public void draw(int x, int y) {
		// TODO Auto-generated method stub
		Graphics graphics = getGraphics();
		graphics.setColor(color);
		graphics.fillOval(x-radius, y-radius, radius*2, radius*2);
	}
	//重新执行命令栈中的命令
	public void paint(Graphics g){
		history.execute();
	}

}

Main类

package Command;

import java.awt.Canvas;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;

public class Main extends JFrame implements ActionListener, MouseMotionListener, WindowListener {
	//创建多命令链对象
	private MacroCommand history = new MacroCommand();
	//初始化画布
	private DrawCanvas canvas = new DrawCanvas(400, 400, history);
	//创建按钮对象
	private JButton clearButton = new JButton("clear");
	public Main(String string){
		super(string);
		//为空间添加事件监听
		this.addWindowListener(this);
		canvas.addMouseMotionListener(this);
		clearButton.addActionListener(this);
		
		//设置布局
		Box buttonnBox = new Box(BoxLayout.X_AXIS);
		buttonnBox.add(clearButton);
		Box mainBox = new Box(BoxLayout.Y_AXIS);
		mainBox.add(buttonnBox);
		mainBox.add(canvas);
		getContentPane().add(mainBox);
		
		pack();
		show();
	}
	@Override
	public void windowOpened(WindowEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void windowClosing(WindowEvent e) {
		// TODO Auto-generated method stub
		System.exit(0);

	}

	@Override
	public void windowClosed(WindowEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void windowIconified(WindowEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void windowDeiconified(WindowEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void windowActivated(WindowEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void windowDeactivated(WindowEvent e) {
		// TODO Auto-generated method stub

	}
	//鼠标拖拽事件发生时,创建一条命令,将该命令加入栈中,执行命令
	@Override
	public void mouseDragged(MouseEvent e) {
		// TODO Auto-generated method stub
		Command cmd = new DrawCommand(canvas,e.getPoint());
		history.append(cmd);
		cmd.execute();
		

	}

	@Override
	public void mouseMoved(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		//如果按下清除键,则清除历史栈中的命令,重新绘制画布
		if(e.getSource() == clearButton){
			history.clear();
			canvas.repaint();
		}
		

	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Main("Command Pattern Sample");

	}

}

设计模式(Java)—Command模式

Command模式类图
设计模式(Java)—Command模式
Command模式时序图
设计模式(Java)—Command模式

相关文章: