1. 程式人生 > >設計模式:命令(Command)模式

設計模式:命令(Command)模式

box exe see 再次 clas sed hist 本質 private

設計模式:命令(Command)模式

一、前言

命令也是類,將命令作為一個類來保存,當要使用的時候可以直接拿來使用,比如腳本語言寫出的腳本,只需要一個命令就能執行得到我們想要的需要操作很長時間才能得到的結果。這是一個非常有意思的模式,將操作的步驟保存下來,本例之中我們使用java自帶的GUI來畫圖,然後將畫圖的過程(在哪個地方畫了什麽東西)保存下來,可以把每一次我們的操作作為一個命令,其實就是<使用什麽畫布,畫點的坐標>,將這個命令對應的對象保存到所有命令對象的集合之中去,這樣命令集合就記錄下來了每一個命令,如果要顯示畫的內容的時候,直接將這些命令組合讀取出來在進行一次重畫即可。通過這種模式保存下來已經執行的步驟,通過重畫再復述出來,是一種非常重要的開發理念,在需要保存歷史紀錄並恢復的場合是非常有用的。

技術分享圖片

二、代碼

Command接口:

1 package zyr.dp.command;
2 
3 public interface Command {
4     public abstract void execute();
5 }

DrawCommand類:

 1 package zyr.dp.command;
 2 
 3 import java.awt.Point;
 4 
 5 
 6 public class DrawCommand implements Command {
 7 
 8     private Drawable drawable;
 9     private
Point position; 10 public DrawCommand(Drawable drawable,Point position){ 11 this.drawable=drawable; 12 this.position=position; 13 } 14 15 public void execute() { 16 drawable.draw(position.x, position.y); 17 } 18 19 }
MacroCommand 類:
 1 package zyr.dp.command;
2 3 import java.util.Iterator; 4 import java.util.Stack; 5 6 public class MacroCommand implements Command { 7 8 Stack commands=new Stack(); 9 10 public void execute() { 11 Iterator it = commands.iterator(); 12 while(it.hasNext()){ 13 Command command=(Command)it.next(); 14 command.execute(); 15 } 16 } 17 18 public void append(Command command){ 19 if(command!=this){ 20 commands.add(command); 21 } 22 } 23 24 public void clear(){ 25 commands.clear(); 26 } 27 28 public void undo(){ 29 if(!commands.isEmpty()){ 30 commands.pop(); 31 } 32 } 33 34 }

Drawable接口:

1 package zyr.dp.command;
2 
3 public interface Drawable {
4 
5     public abstract void draw(int x,int y);
6     
7 }
DrawCanvas 實現類:
 1 package zyr.dp.command;
 2 
 3 import java.awt.*;
 4 import java.util.Random;
 5 
 6 
 7 public class DrawCanvas extends Canvas implements Drawable {
 8 
 9     private static final long serialVersionUID = 1972130370393242746L;
10     
11     private MacroCommand history;
12     private int radius=8;
13 
14     public DrawCanvas(int width,int hieght, MacroCommand history){
15         setSize(width,hieght);
16         setBackground(Color.white);
17         this.history=history;
18     }
19     
20     public void draw(int x, int y) {
21         Random random = new Random();
22         
23         Graphics g = getGraphics();
24         g.setColor((random.nextBoolean())? Color.yellow : Color.MAGENTA);
25         g.fillOval(x-radius, y-radius, radius*2, radius*2);
26     }
27     
28     @Override
29     public void paint(Graphics g) {
30         System.out.println("執行一次刷新!"+System.currentTimeMillis());
31         history.execute();
32     }
33 
34 }

Main類:

  1 package zyr.dp.command;
  2 
  3 import java.awt.event.ActionEvent;
  4 import java.awt.event.ActionListener;
  5 import java.awt.event.MouseEvent;
  6 import java.awt.event.MouseMotionListener;
  7 import java.awt.event.WindowEvent;
  8 import java.awt.event.WindowListener;
  9 
 10 import javax.swing.*;
 11 
 12 
 13 public class Main extends JFrame implements ActionListener,MouseMotionListener,WindowListener{
 14 
 15     private MacroCommand history=new MacroCommand() ;
 16     
 17     private JButton btnClear=new JButton("清除");
 18     private JButton btnRePaint=new JButton("重現");
 19     
 20     private DrawCanvas canvas=new DrawCanvas(400,400,history);
 21     
 22     public Main(String title){
 23         super(title);
 24         
 25         this.addWindowListener(this);
 26         canvas.addMouseMotionListener(this);
 27         btnClear.addActionListener(this);
 28         btnRePaint.addActionListener(this);
 29         
 30         Box btnBox=new Box(BoxLayout.X_AXIS);
 31         btnBox.add(btnClear);
 32         btnBox.add(btnRePaint);
 33         
 34         Box mainBox=new Box(BoxLayout.Y_AXIS);
 35         mainBox.add(btnBox);
 36         mainBox.add(canvas);
 37         
 38         getContentPane().add(mainBox);
 39         
 40         pack();
 41         show();
 42     }
 43     
 44     public static void main(String[] args) {
 45 
 46         new Main("命令模式");
 47         
 48     }
 49 
 50     
 51     @Override
 52     public void actionPerformed(ActionEvent e) {
 53         if(e.getSource()==btnClear){
 54             history.clear();
 55             canvas.repaint();
 56         }else if(e.getSource()==btnRePaint){
 57             canvas.repaint();
 58         }
 59     }
 60 
 61 
 62     @Override
 63     public void mouseDragged(MouseEvent e) {
 64         Command cmd=new DrawCommand(canvas,e.getPoint());
 65         history.append(cmd);
 66         cmd.execute();
 67     }
 68 
 69     @Override
 70     public void windowClosing(WindowEvent e) {
 71         System.exit(0);
 72     }
 73 
 74     
 75     
 76 
 77     @Override
 78     public void windowOpened(WindowEvent e) {
 79     }
 80     
 81     @Override
 82     public void windowClosed(WindowEvent e) {
 83     }
 84     
 85     @Override
 86     public void windowIconified(WindowEvent e) {
 87     }
 88 
 89     @Override
 90     public void windowDeiconified(WindowEvent e) {
 91     }
 92 
 93     @Override
 94     public void windowActivated(WindowEvent e) {
 95     }
 96 
 97     @Override
 98     public void windowDeactivated(WindowEvent e) {
 99     }
100 
101     @Override
102     public void mouseMoved(MouseEvent e) {
103     }
104 }

實驗結果:

技術分享圖片

由此我們可以看到保存了的命令就這樣一個個的再次執行了一遍,是不是很有意思呢?!

三、總結

對於命令模式,在本例之中使用了Composite模式,叠代器等模式作為輔助,另外在生成對象的時候還可能使用原型模式,在保存命令的時候還可能使用備忘錄模式。本例是一個很好的例子,從本質上說明了命令模式就是將命令抽象成一個類,通過保存接收者的引用,在後期還可以讓接收者去執行,同樣的使用了組合模式將這些對象一個個的保存了下來,然後一步步的調用單個命令的執行方法,該執行方法通知命令的接收者去再次執行命令,這種方式特別的方便,因為我們保存的是用戶的操作,能夠一直記錄下來,甚至可以保存到文件之中以後可以恢復,由此可以看到命令模式的強大。

設計模式:命令(Command)模式