設計模式學習筆記——命令(Command)模式
@(設計模式)[設計模式, 命令模式, command]
基本介紹
將一個請求封裝爲一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可撤消的操作。
命令案例
類圖
實現代碼
Command接口
package com.pc.command.example.command;
/**
* 命令接口
* Created by Switch on 2017/3/31.
*/
public interface Command {
/**
* 執行
*/
void execute();
}
MacroCommand類
package com.pc.command.example.command;
import java.util.Iterator;
import java.util.Stack;
/**
* 大量命令類
* Created by Switch on 2017/3/31.
*/
public class MacroCommand implements Command {
/**
* 命令的集合
*/
private Stack<Command> commands = new Stack<>();
@Override
public void execute() {
Iterator<Command> it = commands.iterator();
while (it.hasNext()) {
it.next().execute();
}
}
/**
* 添加命令
*
* @param cmd 命令
*/
public void append(Command cmd) {
if (cmd != this) {
commands.push(cmd);
}
}
/**
* 刪除最後一條命令
*/
public void undo() {
if (!commands.empty()) {
commands.pop();
}
}
/**
* 刪除所有命令
*/
public void clear() {
commands.clear();
}
}
Drawable接口
package com.pc.command.example.drawer;
/**
* 繪圖接口
*/
public interface Drawable {
/**
* 繪製
*
* @param x x座標
* @param y y座標
*/
void draw(int x, int y);
}
DrawCommand類
package com.pc.command.example.drawer;
import com.pc.command.example.command.Command;
import java.awt.*;
/**
* 繪圖命令類
*/
public class DrawCommand implements Command {
/**
* 繪製對象
*/
protected Drawable drawable;
/**
* 繪製位置
*/
private Point position;
public DrawCommand(Drawable drawable, Point position) {
this.drawable = drawable;
this.position = position;
}
@Override
public void execute() {
drawable.draw(position.x, position.y);
}
}
DrawCanvas類
package com.pc.command.example.drawer;
import com.pc.command.example.command.MacroCommand;
import java.awt.*;
/**
* 繪製面板類
*/
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) {
setSize(width, height);
setBackground(Color.white);
this.history = history;
}
@Override
public void paint(Graphics g) {
history.execute();
}
@Override
public void draw(int x, int y) {
Graphics g = getGraphics();
g.setColor(color);
g.fillOval(x - radius, y - radius, radius * 2, radius * 2);
}
}
測試類
package com.pc.command.example.test;
import com.pc.command.example.command.Command;
import com.pc.command.example.command.MacroCommand;
import com.pc.command.example.drawer.DrawCanvas;
import com.pc.command.example.drawer.DrawCommand;
import javax.swing.*;
import java.awt.event.*;
/**
* MacroCommand Tester.
*
* @author Switch
* @version 1.0
*/
public class CommandTest 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 CommandTest(String title) {
super(title);
this.addWindowListener(this);
canvas.addMouseMotionListener(this);
clearButton.addActionListener(this);
Box buttonBox = new Box(BoxLayout.X_AXIS);
buttonBox.add(clearButton);
Box mainBox = new Box(BoxLayout.Y_AXIS);
mainBox.add(buttonBox);
mainBox.add(canvas);
getContentPane().add(mainBox);
pack();
show();
}
// ActionListener接口中的方法
public void actionPerformed(ActionEvent e) {
if (e.getSource() == clearButton) {
history.clear();
canvas.repaint();
}
}
// MouseMotionListener接口中的方法
public void mouseMoved(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
Command cmd = new DrawCommand(canvas, e.getPoint());
history.append(cmd);
cmd.execute();
}
// WindowListener接口中的方法
public void windowClosing(WindowEvent e) {
System.exit(0);
}
public void windowActivated(WindowEvent e) {
}
public void windowClosed(WindowEvent e) {
}
public void windowDeactivated(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowOpened(WindowEvent e) {
}
public static void main(String[] args) {
new CommandTest("Command Pattern Sample");
}
}
運行結果
命令模式中的角色
Command(命令)
Command
角色負責定義命令的接口(API
)。在案例中,由Command
接口扮演此角色。
ConcreteCommand(具體的命令)
ConcreteCommand
角色負責實現在Command
角色中定義的接口(API
)。在案例中,由MacroCommand
類和DrawCommand
類扮演此角色。
Receiver(接收者)
Receiver
角色是Command
角色執行命令時的對象,也可以稱其爲命令接收者。在案例中,由DrawCanvas
類接收DrawCanvas
類和DrawCommand
類扮演此角色。
Client(請求者)
Client
角色負責生成ConcreteCommand
角色並分配Receiver
角色。在案例中,由測試類扮演此角色。在響應鼠標拖拽事件時,它生成了DrawComrnand
類的實例,並將扮演Receiver
角色的DrawCanvas
類的實例傳遞給了DrawCommand
類的構造函數。
Invoker(發動者)
Invoker
角色是開始執行命令的角色,它會調用在Command
角色中定義的接口(API
)。在案例中,由測試和DrawCanvas
類扮演此角色。這兩個類都調用了Command
接口中的execute
方法。測試類同時扮演了Client
角色和Invoker
角色。
類圖
時序圖
GitHub:DesignPatternStudy
——————參考《圖解設計模式》