Command模式(命令設計模式)


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....

}
  • 相關設計模式
  1. ◆Composite模式(第11章)有時會使用Composite模式實現宏命令(macrocommand)。
  2. ◆Memento模式(第18章)有時會使用Memento模式來保存Command角色的歷史記錄。
  3. ◆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) {

    }
}





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM