举个栗子

指挥官向士兵下达命令,士兵执行

实现代码如下:

class Soldier {
public void exe() {
System.out.println("执行命令");
}
} class Commander {
public void invok() {
Soldier soldier=new Soldier();
soldier.exe();
}
}

代码问题

上诉代码是最基本的一个实现,存在问题:

  1. Commander和Soldier高度耦合
  2. 新增命令的话,要改动Commander类,扩展性不好(影响已有实现),不符合OCP原则
  3. 指挥官指挥实现多条命令时,又要改Commander
  4. 士兵执行命令时如果加一些控制的话,如记录日志、延缓执行,加到哪都不合适,SRP和OCP原则。

重构后代码

class Soldier {
public void doCommandA() {
System.out.println("执行命令A");
}
public void doCommandB() {
System.out.println("执行命令B");
}
} class CommandCenterA implements Command{
Soldier soldier;
public CommandCenterA(Soldier soldier) {
this.soldier=soldier;
} @Override
public void exe() {
waitTime();
soldier.doCommandA();
soldier.doCommandB();
}
private void waitTime() {
System.out.println("延迟执行");
} } class Commander {
Command command;
public Commander(Command command) {
this.command=command;
}
public void exe(){
command.exe();
}
} class Client{
public static void main(String[] args) {
Soldier soldier=new Soldier();
Command command=new CommandCenterA(soldier);//将soldier注入到命令中心
Commander commander=new Commander(command);//将命令中心注入到指挥官
commander.exe();
}

解决的问题

  1. Commander和Soldier隔离,解除耦合,
  2. 新增命令时,只需新增Command接口的实现CommandCenter,实现对命令和请求控制
  3. CommandCenter可以实现复合命令,延迟执行,记录日志等

命令模式

命令模式把一个请求或者操作封装到一个对象中,并把发出命令和执行命令隔离,使得发出命令不必关心命令如何执行。

讲个实例:

比如开关灯和开关空调。

最原始的,就是把两根电线连到一起,灯亮空调开,断开,灯灭空调关。(Receiver)

现在我们加了个开关,开关不仅能开灯,还能开空调。(将电灯开关和空调开关进一步抽象)

开关内部的实现,就是我们的命令中心。(开空调时可以设置温度,开灯时可以延缓执行)

将开关和电线隔离,并加入了我们对命令的具体控制。这就是命令模式。

Java实现要点 Invoker(请求者)+Commander(命令中心)+Receiver(执行者)

  1. 将请求者和执行者,加入中间层“命令中心”,将请求者对象绑定于一个动作
  2. 将命令中心抽象出接口,使得请求者依赖于接口而不是具体实现
  3. 命令中心实现对请求者和执行者的解耦

JDK中的命令模式

比较经典的应该就是Runnable了吧。

//执行者
Runnable soldier= new Runnable() {
public void run() {
System.out.println("执行命令");
}
};
//命令中心
Runnable thread=new Thread(solder);//可继承Thread继续定制
thread.sleep(1000);
//请求者
thread.start();

Thread源码:

/* What will be run. */
private Runnable target; public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
/**
* If this thread was constructed using a separate
* <code>Runnable</code> run object, then that
* <code>Runnable</code> object's <code>run</code> method is called;
* otherwise, this method does nothing and returns.
* <p>
* Subclasses of <code>Thread</code> should override this method.
*
* @see #start()
* @see #stop()
* @see #Thread(ThreadGroup, Runnable, String)
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}

注入了Runnable,并实现了对Runnable的控制。

优点

  1. 松耦合
  2. “命令中心”对命令可控(如日志化,延缓,复合命令),对请求可控(如队列,参数化)
  3. 扩展性。只需要实现新的“命令中心”即可,任意装配,并且不影响已有的实现,因为命令发起者(指挥官)中的命令中心时接口注入。

命令模式/command模式/行为型模式的更多相关文章

  1. NET设计模式 第二部分 创建型模式(6):创建型模式专题总结(Creational Pattern)

    创建型模式专题总结(Creational Pattern) ——.NET设计模式系列之七 Terrylee,2006年1月 概述 创建型模式,就是用来创建对象的模式,抽象了实例化的过程.它帮助一个系统 ...

  2. 抽象工厂模式(abstract)创建型模式

    (一)简单工厂模式? 现在的学习是面向对象面向接口的,但是执行时的操作需要实例化后的对象.随着我们需要的类的增加,我们就需要把这些共同的东西提取出来,放在一个抽象类中,让这些子类来继承抽象类.当我们调 ...

  3. 设计模式学习之命令模式(Command,行为型模式)(12)

    一.命令模式的定义 命令模式属于对象的行为型模式.命令模式是把一个操作或者行为抽象为一个对象中,通过对命令的抽象化来使得发出命令的责任和执行命令的责任分隔开.命令模式的实现可以提供命令的撤销和恢复功能 ...

  4. 设计模式学习之建造者模式(Builder,创建型模式)(6)

    假如我们需要建造一个房子,并且我们也不知道如何去建造房子,所以就去找别人帮我们造房子 第一步: 新建一个房子类House,里面有房子该有的属性,我们去找房子建造者接口HouseBuilder,我们要建 ...

  5. 设计模式学习之原型模式(Prototype,创建型模式)(5)

    通过序列化的方式实现深拷贝 [Serializable] public class Person:ICloneable { public string Name { get; set; } publi ...

  6. ANDROID 中设计模式的采用--创建型模式

     所谓模式就是在某一情景下解决某个问题的固定解决方案. 所有的创建型模式都是用作对象的创建或实例化的解决方案. 1 简单工厂模式 创建对象的最简单方法是使用new来创建一个对象,如果只创建一种固定 ...

  7. 设计模式学习之模板方法模式(TemplateMethod,行为型模式)(9)

    一.什么是模板方法模式 Template Method模式也叫模板方法模式,是行为模式之一,它把具有特定步骤算法中的某些必要的处理委让给抽象方法,通过子类继承对抽象方法的不同实现改变整个算法的行为. ...

  8. 七、备忘录模式Memento(行为型模式)

    其目的是,在不违反封装原则的前提下.採集和备份一个对象的内部状态以便这个对象能够在以后恢复到之前的某个状态. 在Memento模式中,有例如以下角色: 1.Memento (备忘录) * 存储Orig ...

  9. 设计模式-抽象工厂模式(AbstractFactory)(创建型模式)

    //以下代码来源: 设计模式精解-GoF 23种设计模式解析附C++实现源码 //Product.h #pragma once class AbstractProductA { public: vir ...

  10. GoF的23种设计模式之行为型模式的特点和分类(2)

    行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配. 行为型模式分为类行为模式和对象行为模式,前者采用继 ...

随机推荐

  1. Flatten 2D Vector

    Implement an iterator to flatten a 2d vector. For example, Given 2d vector = [ [1,2], [3], [4,5,6] ] ...

  2. 深入理解 Win32 PE 文件格式

    深入理解 Win32 PE 文件格式 Matt Pietrek 这篇文章假定你熟悉C++和Win32. 概述 理解可移植可执行文件格式(PE)可以更好地了解操作系统.如果你知道DLL和EXE中都有些什 ...

  3. irc操作小记

    IRC客户端 HexChat 跨平台支持,目前正在Windows上使用,暂无不满意的地方 polari 支持的命令太少了,功能有限. Empathy 重量级,支持各种消息协议 weechat/irss ...

  4. Selenium webdriver 操作日历控件

    一般的日期控件都是input标签下弹出来的,如果使用webdriver 去设置日期, 1. 定位到该input 2. 使用sendKeys 方法 比如: 但是,有的日期控件是readonly的 比如1 ...

  5. hibernate xx(tableName) is not mapped

    数据库中表名是:book,数据库表名不区分大小写的 之后我在hibernate 使用book, String sql="from book"; Query query=sessio ...

  6. ffmpeg-20160813-bin.7z

    ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 S 下一帧 [ -2秒 ] +2秒 ; -1秒 ' +1秒 下一个帧 -> -5秒 f ...

  7. ZOJ 3812 We Need Medicine(dp、背包、状态压缩、路径记录)

    参考:http://blog.csdn.net/qian99/article/details/39138329 参考的链接里说明得很好,注释也很好...thanks for sharing 朴素的想法 ...

  8. 关于内核调试(Windbg)的虚拟机配置问题

    注:本文配置 环境为VMware® Workstation11.1.2 build-2780323+Windows xp SP2+Windbg 6.12.0002.63 x86 *在win7以后的操作 ...

  9. 【python】入门学习(八)

    异常处理: python在遇到问题时会自动引发异常,也可以用raise故意引发异常,异常种类必须是已有的 >>> raise IOError('This is a test.') T ...

  10. 【python】time,datetime,string相互转换

    来源:http://essen.iteye.com/blog/1452098 #把datetime转成字符串 def datetime_toString(dt): return dt.strftime ...