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) { }
}

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

  1. 命令模式 Command 行为型 设计模式(十八)

    命令模式(Command) 请分析上图中这条命令的涉及到的角色以及执行过程,一种可能的理解方式是这样子的: 涉及角色为:大狗子和大狗子他妈 过程为:大狗子他妈角色 调用 大狗子的“回家吃饭”方法 引子 ...

  2. Java设计模式(22)命令模式(Command模式)

    Command模式是最让我疑惑的一个模式,我在阅读了很多代码后,才感觉隐约掌握其大概原理,我认为理解设计模式最主要是掌握起原理构造,这样才对自己实际编程有指导作用.Command模式实际上不是个很具体 ...

  3. python 设计模式之命令(Command)模式

    #写在前面 也了解了不少设计模式了,他们都有一个通病,那就是喜欢把简单的东西复杂化.比如在不同的类中加个第三者.哈哈哈,简单变复杂是有目的的,那就是降低耦合度,增强可维护性,提高代码复用性,使代码变得 ...

  4. 设计模式C++描述----19.命令(Command)模式

    一. 举例说明 我们知道,在多线程程序中,多个用户都给系统发 Read 和 Write 命令.这里有几点需要说明: 1. 首先明确一点,所有的这些 Read 和 Write 命令都是调用一个库函数. ...

  5. 设计模式之美:Command(命令)

    索引 别名 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):直接注入 Receiver 对象,Command 决定调用哪个方法. 实现方式(二):注入 Receiver 的指定方法, ...

  6. Command Pattern -- 命令模式原理及实现(C++)

    主要参考<大话设计模式>和<设计模式:可复用面向对象软件的基础>两本书.本文介绍命令模式的实现. What it is:Encapsulate a request as an ...

  7. 开发设计模式(一)Command模式

    Command定义 将来自客户端的请求传入一个对象,无需了解这个请求激活的 动作或有关接受这个请求的处理细节. 这是一种两台机器之间通讯联系性质的模式,类似传统过程语 言的 CallBack功能. 优 ...

  8. 设计模式之Command(命令)(转)

    Command模式是最让我疑惑的一个模式,我在阅读了很多代码后,才感觉隐约掌握其大概原理,我认为理解设计模式最主要是掌握起原理构造,这样才对自己实际编程有指导作用.Command模式实际上不是个很具体 ...

  9. Command Pattern 命令模式

    定义: 命令模式将‘请求’封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象,命令模式也支持可撤销的操作. 类图 如上图所示:Command类是用来声明执行操作的接口:ConcreteCom ...

随机推荐

  1. E比昨天更多的棒棒糖(Easy+Hrad)(华师网络赛)(DP||母函数||背包优化)

    Time limit per test: 2.0 seconds Memory limit: 512 megabytes 唐纳德先生的某女性朋友最近与唐纳德先生同居.该女性朋友携带一 baby.该 b ...

  2. LeetCode 510. Inorder Successor in BST II

    原题链接在这里:https://leetcode.com/problems/inorder-successor-in-bst-ii/ 题目: Given a binary search tree an ...

  3. bzoj 3572: [Hnoi2014]世界树 虚树

    题目: Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生 ...

  4. backbonejs学习

    文章: http://www.cnblogs.com/yexiaochai/archive/2013/07/27/3219402.html http://blog.csdn.net/cony100/a ...

  5. hdu 5909 Tree Cutting —— 点分治

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909 点分治,每次的 rt 是必选的点: 考虑必须选根的一个连通块,可以DP,决策就是在每个子树中决定选不 ...

  6. MySQL on Azure高可用性设计 DRBD - Corosync - Pacemaker - CRM (一)

    MySQL迁移到Azure上后,由于云的特性,在自建数据中心的MySQL的HA的方法在云上很多都不能部署. 这主要是因为,目前Public Cloud不支持:1. 共享存储:2. Multicast: ...

  7. mysql: not unique table/alias error. 如何解决

    1.请检查出现问题位置的 SQL 语句中是否使用了相同的表名,或是定义了相同的表别名. 2.检查 SELECT 语句中要查询的字段名是不是定义重复,或者没有定义. 3.把你的sql语句中的换行去掉.一 ...

  8. 【转】 Pro Android学习笔记(六八):HTTP服务(2):HTTP POST

    目录(?)[-] 找一个测试网站 HTTP POST小例子 上次学习了HTTP GET请求,这次学习一下HTTP POST. 找一个测试网站 小例子好写,但要找个测试网站就有些麻烦,一下子无从入手,都 ...

  9. ETL之Tungsten Replicator

    1 概述 1.1 介绍 Tungsten Replicator是数据库集群和复制供应商Continuent推出的高性能.开源的数据复制引擎,是Continuent最先进的集群解决方案的核心组件之一,特 ...

  10. js基础之变量类型

    1.NAN(Not a number) 不是一个数字 自身:console.log(NaN==NaN)和console.log(NaN===NaN)返回值都是false; 其他函数,isNaN()可用 ...