1. Command模式
命令也是类。对对象的请求不是直接给对象发送请求消息,而是,通过命令对象,让命令对象去执行相应的操作,即将请求封装成命令。同时请求也变为可记录的,可以d做到支持撤销等操作。
1.1 Command模式的类图
登场角色
-
Command(命令)
定义了命令接口 -
ConcreteCommand(具体的命令)
具体的命令实现类 -
Receiver(接收者)
命令(动作、事件)的接收者,非命令模式下,是由调用者直接调用Receiver方法来完成该请求。 -
Client(请求者)
负责生成ConcreteCommand实例并分配Receiver角色 -
Invoker(发动者)
执行命令的角色,即调用Command命令接口的角色。
1.2 示例程序
类一览表:
名字 | 说明 |
---|---|
Command | 表示"命令"的接口 |
MacroCommand | "由多条命令整合成的命令"的类 |
DrawCommand | "绘制一个点的命令"类 |
Drawable | "绘制对象"的接口 |
DrawCanvas | 实现"绘制对象"的类,扮演了Client |
Main | 测试程序行为的类,扮演了Client和Invoker |
uml类图(只含实现关系)
uml类图
Command接口
package xin.ajay.command;
public interface Command {
void execute();
}
MacroCommand类
package xin.ajay.command;
import java.util.Iterator;
import java.util.Stack;
public class MacroCommand implements Command{
private Stack<Command> commands = new Stack<>();
@Override
public void execute() {
for (Command command : commands) {
command.execute();
}
}
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 xin.ajay.command.drawer;
public interface Drawable {
void draw(int x,int y);
}
DrawCanvas类
package xin.ajay.command.drawer;
import xin.ajay.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 print(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);
}
}
DrawCommand类
package xin.ajay.command.drawer;
import xin.ajay.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;
}
public void execute(){
drawable.draw(position.x,position.y);
}
}
Main类
package xin.ajay.command.drawer;
import xin.ajay.command.Command;
import xin.ajay.command.MacroCommand;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
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 title) throws HeadlessException {
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);
add(mainBox);
pack();
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == clearButton) {
history.clear();
canvas.repaint();
}
}
@Override
public void mouseDragged(MouseEvent e) {
Command drawCommand = new DrawCommand(canvas, e.getPoint());
history.append(drawCommand);
drawCommand.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) {
}
public static void main(String[] args) {
new Main("Command Pattern Sample");
}
}
结果
鸣谢
GoF《设计模式》和结城浩的《图解设计模式》