Command??
把方法的調用用一個類的實例來承載,要管理工作的歷史記錄,創建這些方法執行的命令的集合,只需管理這些實例的集合即可,而且還可以隨時再次執行過去的命令,或是將多個過去的命令整合為一個新命令並執行。稱之為Command設計模式
- 那里合適使用:
Command有時也被稱為事件(event)。它與“事件驅動編程”中的“事件”是一樣的意思。當發生點擊鼠標、按下鍵盤按鍵等事件時,我們可以先將這些事件作成實例,然后按照發生順序放入隊列中。接着,再依次去處理它們。在GUI(graphical user interface)編程中,經常需要與“事件”打交道。即為在有多個命令,並且這些命令有一定的邏輯順序,且可能需要保存的這些命令的數據,那么可以使用Command設計模式。
理清職責
-
實現簡單的畫圖板:
|包=名字說明
|command |command表示“命令”的接口
|command |Macrocommand |表示“由多條命令整合成的命令”的類
|drawer |Drawcommand |表示“繪制一個點的命令”的類
|drawer |Drawable|表示“繪制對象”的接口
|drawer |Drawcanvas實現“繪制對象”的類
|無名|MainT測試程序行為的類 -
擴展命令:
只需要實現command,並且關聯操作的屬性類即可
ColorCommand implements Command {
private xxxAction xxxx;
private XxxArgs xxxx;
xxxxAction....
}
- 相關設計模式
- ◆Composite模式(第11章)有時會使用Composite模式實現宏命令(macrocommand)。
- ◆Memento模式(第18章)有時會使用Memento模式來保存Command角色的歷史記錄。
- ◆Protype模式(第6章)有時會使用Protype模式復制發生的事件(生成的命令)。
UML
時序圖:
Code
- Comamnd 包
public interface Command {
void execute();
}
public class MacroCommand implements Command {
// 命令集合 便於執行UNdo操作
private Stack commands=new Stack();
// 執行stack中所有命令
@Override
public void execute() {
Iterator it = commands.iterator();
while (it.hasNext()){
Command o = ((Command) it.next());
o.execute();
}
}
public void append(Command command){
if (command!=null){
commands.add(command);
}
}
// 移除末尾命令
public void undo(){
if(!commands.empty()){
commands.pop();
}
}
// 移除所有命令
public void clear(){
commands.clear();
}
}
- Drawer 包
public interface Drawable {
void draw(int x,int y);
void setColor(Color color);
}
public class ColorCommand implements Command {
private Drawable drawable;
private Color color;
public ColorCommand(Drawable drawable, Color color) {
this.drawable = drawable;
this.color = color;
}
@Override
public void execute() {
drawable.setColor(color);
}
}
public class DrawCommand implements Command {
// 繪制對象
private Drawable drawable;
// 繪制位置
private Point point;
public DrawCommand(Drawable drawable, Point point) {
this.drawable = drawable;
this.point = point;
}
@Override
public void execute() {
drawable.draw(point.x,point.y);
}
}
public class DrawCanvas extends Canvas implements Drawable {
// defulat 顏色
private Color color=Color.red;
private int radius=6;
private MacroCommand history;
private Graphics2D graphics;
public DrawCanvas(int width,int height,MacroCommand history) {
setSize(width,height);
setBackground(Color.white);
this.history=history;
}
// 重新繪制
@Override
public void paint(Graphics graphics){
history.execute();
}
/**
* 這里的實現的畫點軌跡依據本身物理操作的手勢的速度定型的,
* 即為:手快 畫點 手慢 畫線
* @param x
* @param y
*/
@Override
public void draw(int x, int y) {
graphics = (Graphics2D) getGraphics();
graphics.fillOval(x-radius,y-radius,radius*2,radius*2);
//graphics.drawOval(x-radius,y-radius,radius*2,radius*2);
}
@Override
public void setColor(Color color) {
graphics = (Graphics2D) getGraphics();
graphics.setColor(color);
}
}
- MainT
public class MainT extends JFrame implements ActionListener, MouseMotionListener, WindowListener {
private MacroCommand history=new MacroCommand();
private DrawCanvas canvas=new DrawCanvas(500,500,history);
private JButton clearbtn=new JButton("clear");
private JButton undobtn=new JButton("撤銷");
public MainT(String title) {
super(title);
setLocationRelativeTo(getComponentAt(-500,-500));
this.addWindowListener(this);
canvas.addMouseMotionListener(this);
clearbtn.addActionListener(this);
undobtn.addActionListener(this);
Box btnbox=new Box(BoxLayout.X_AXIS);
btnbox.add(clearbtn);
btnbox.add(undobtn);
Box mainbox=new Box(BoxLayout.Y_AXIS);
mainbox.add(canvas);
mainbox.add(btnbox);
getContentPane().add(mainbox);
pack();
show();
}
public static void main(String[] args) {
new MainT("mspaint");
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==clearbtn){
history.clear();
canvas.repaint();
}else if(e.getSource()==undobtn){
history.undo();
canvas.repaint();
}
}
@Override
public void mouseDragged(MouseEvent e) {
/**
* DrawCommand實際命令的承載者 原來的歷史得以在類中進行保存;
* 如果構建新的命令xxxCommand的實現者,那么在原始記錄中把新版的命令得以getXXx方法拿到,
* 在進行的新的保存的,那么原始數據就可以在新的canvans中得以呈現。
* (實際上canvas可以作為一個單例,在app中存在)
*/
DrawCommand command = new DrawCommand(canvas, e.getPoint());
ColorCommand colorCommand = new ColorCommand(canvas, Color.blue);
history.append(colorCommand);
history.append(command);
colorCommand.execute();
command.execute();
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
@Override
public void windowClosed(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
}