设计模式(JAVA)——Command模式

1. Command模式

命令也是类。对对象的请求不是直接给对象发送请求消息,而是,通过命令对象,让命令对象去执行相应的操作,即将请求封装成命令。同时请求也变为可记录的,可以d做到支持撤销等操作。

1.1 Command模式的类图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jaF5ziYd-1575085314166)(./resources/image/22/22-1_Command.png)]

登场角色

  • Command(命令)
    定义了命令接口

  • ConcreteCommand(具体的命令)
    具体的命令实现类

  • Receiver(接收者)
    命令(动作、事件)的接收者,非命令模式下,是由调用者直接调用Receiver方法来完成该请求。

  • Client(请求者)
    负责生成ConcreteCommand实例并分配Receiver角色

  • Invoker(发动者)
    执行命令的角色,即调用Command命令接口的角色。

1.2 示例程序

类一览表:

名字说明
Command表示"命令"的接口
MacroCommand"由多条命令整合成的命令"的类
DrawCommand"绘制一个点的命令"类
Drawable"绘制对象"的接口
DrawCanvas实现"绘制对象"的类,扮演了Client
Main测试程序行为的类,扮演了Client和Invoker

uml类图(只含实现关系)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ywW7tNoy-1575085314167)(./resources/image/22/22-2.png)]

uml类图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lq7FQw0R-1575085314169)(./resources/image/22/22-3.png)]

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

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JIc4UQRe-1575085314172)(./resources/image/22/22-4.png)]

鸣谢

GoF《设计模式》和结城浩的《图解设计模式》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值