1. 程式人生 > >設計模式(Java)—Command模式

設計模式(Java)—Command模式

一個類在進行工作時會呼叫自己或是其他類的方法,雖然呼叫結果會反映在物件的狀態中,但是並不會留下工作的歷史紀錄。 這時,如果有一個類,用來表示進行這項工作的命令就會方便很多。每一項想做的工作就不再是方法的呼叫這種動態處理了,而是一個表示命令的類的例項,既可以用物來表示,要想管理工作的歷史紀錄,只需管理這些例項的集合即可,而且還可以隨時再次執行過去的命令,或是將多個過去的命令整合為一個新命令並執行。 在設計模式中,我們稱這樣的命令為Command模式。

示例程式 這段示例程式是一個畫圖軟體,使用者拖動滑鼠時程式會繪製出紅色圓點,點選clear按鈕後會清除所有圓點。 使用者每拖動一次滑鼠,應用程式都會為“在這個位置畫一個點”這條命令生成一個DrawCommand類的例項,只要儲存了這條例項,以後有需要時就可以重新繪製。

在這裡插入圖片描述

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");

	}

}

在這裡插入圖片描述

Command模式類圖 在這裡插入圖片描述 Command模式時序圖 在這裡插入圖片描述