设计模式:命令(Command)模式

设计模式:命令(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模式,迭代器等模式作为辅助,另外在生成对象的时候还可能使用原型模式,在保存命令的时候还可能使用备忘录模式。本例是一个很好的例子,从本质上说明了命令模式就是将命令抽象成一个类,通过保存接收者的引用,在后期还可以让接收者去执行,同样的使用了组合模式将这些对象一个个的保存了下来,然后一步步的调用单个命令的执行方法,该执行方法通知命令的接收者去再次执行命令,这种方式特别的方便,因为我们保存的是用户的操作,能够一直记录下来,甚至可以保存到文件之中以后可以恢复,由此可以看到命令模式的强大。

原文地址:https://www.cnblogs.com/zyrblog/p/9252664.html

时间: 2024-10-29 19:09:45

设计模式:命令(Command)模式的相关文章

23种设计模式(19)---Command模式

命令(Command)模式属于对象的行为模式[GOF95].命令模式又称为行动(Action)模式或交易(Transaction)模式.命令模式把一个请求或者操作封装到一个对象中.命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能. 命令模式是对命令的封装.命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象. 每一个命令都是一个操作:请求的一方发出请求要求执行一个操作:接收的一方收到请求,并执行操作.命令模式允许请求的一方和接收的

Java 实现命令(Command)模式

类图 public interface ICommand { void execute(); } public class ConcreteCommand implements ICommand { private Receiver receiver; public ConcreteCommand(Receiver receiver) { this.receiver = receiver; } @Override public void execute() { this.receiver.act

设计模式 命令-Command

命令-Command 当要向不同类的对象发出相同的请求时,可以将接收者和他的动作封装进一个命令对象.这样调用者只和命令产生依赖.而不会和众多的接收者发生依赖. Head First例子 要设计一款遥控器,控制家里不同的灯或电器.有7个控制栏,上面有开和关按钮.这里遥控器不直接调用灯或电器.因为那是具体的实现,不稳定.引入Command对象.每个按钮按下,就执行相关命令的execute方法.针对不同的电器实现一些列的OnCommand和OffCommand类.里面封装了具体的灯或电器.在构造时传入

设计模式之Command模式(笔记)

命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作. 首先定义一个Receiver类,用来执行请求 public class Receiver { public void action(){ System.out.println("执行请求"); } } 接着定义Command抽象类,用来声明执行操作的接口 public abstract class Commands { protected Receiver re

Command模式(C++命令模式)

重新温习GOF23到第19个命令模式了,写下来方便自己理解 用经理,秘书,邮局来理解这个模式还是比较好的. 经理:喂,小丽呀,这儿有封信,请帮我尽快寄出去- 秘书:好的,经理,我马上去办! 秘书拿着这封信,到一家邮局将信寄了出去.邮局最终也将信投递到了收件人手中. 这是一个很常见的生活工作场景,不过这里面:经理.秘书和邮局,三者在不知不觉间,演绎了一出面向对象设计模式:Command模式.Command模式是我打算讲的第一个行为型设计模式. Command模式的内容大致如此: 将一个请求封装成一

Command 模式 Step by step

提起Command模式,我想没有什么比遥控器的例子更能说明问题了,本文将通过它来一步步实现GOF的Command模式. 我们先看下这个遥控器程序的需求:假如我们需要为家里的电器设计一个远程遥控器,通过这个控制器,我们可以控制电器(诸如灯.风扇.空调等)的开关.我们的控制器上有一系列的按钮,分别对应家中的某个电器,当我们在遥控器上按下"On"时,电器打开:当我们按下"Off"时,电器关闭. 好了,让我们开始Command 模式之旅吧. HardCoding的实现方式

设计模式--命令模式(Command)

基本概念: Command模式也叫命令模式 ,是行为设计模式的一种.Command模式通过被称为Command的类封装了对目标对象的调用行为以及调用参数,命令模式将方法调用给封装起来了. 命令模式的几个角色: Command: 抽象命令类 ConcreteCommand: 具体命令类 Invoker: 调用者 Receiver: 接收者 Client:客户类 命令模式的优缺点: 优点 1. 降低了系统耦合度 2. 新的命令可以很容易添加到系统中去. 缺点 使用命令模式可能会导致某些系统有过多的具

设计模式 - 命令模式(command pattern) 具体解释

命令模式(command pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 命令模式(command pattern) : 将请求封装成对象, 以便使用不同的请求\队列\日志来參数化其它对象. 命令模式也能够支持撤销操作. 简单的命令模式的实现: 1. 详细的类, 每个类都有特定的方法: /** * @time 2014年6月9日 */ package command; /** * @author C.L.Wang * */ publ

设计模式 - 命令模式(command pattern) 详解

命令模式(command pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy 命令模式: 将请求封装成对象, 以便使用不同的请求\队列\日志来参数化其他对象. 命令模式也支持可撤销操作. 命令模式: 调用者(Invoker); 命令(Command): 可执行方法(execute), 具体命令(Concrete Command); 接受者(Receiver): 调用命令(Set Command); 具体方法: 1. 具体对象. /** *

设计模式 - 命令模式(command pattern) 多命令 详解

命令模式(command pattern) 多命令 详解 本文地址: http://blog.csdn.net/caroline_wendy 参考命令模式: http://blog.csdn.net/caroline_wendy/article/details/31379977 具体步骤: 1. 多命令, 把未使用的命令, 初始化为空对象(NoCommand), 根据参数(slot), 选择输出命令. /** * @time 2014年6月16日 */ package command; /**