设计模式学习笔记——命令(Command)模式

设计模式学习笔记——命令(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

——————参考《图解设计模式》

猜你喜欢

转载自blog.csdn.net/q547550831/article/details/70155962