命令模式是其它很多行为型模式的基础模式。
策略模式是命令模式的一个特例,而策略模式又和模板方法模式都是算法替换的实现,只不过替换的方式不同。
下面来谈谈这三个模式。

命令模式

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。

java中传递(注入)对象很容易,但是却不支持直接传递行为(即传递函数或者说传递方法),只能间接的通过传递(注入)一个对象,再调用它的行为来实现。
如果把这样的行为抽取出来为一个类,称作命令类,它的具体实现都是命令对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Receiver {
public void action() {
}
}
public interface ICommand {
void execute();
}
public class Command implements ICommand {
// 注入真正的行为对象
private Receiver receiver;
public void setReceiver(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
// 这里可以包含更多的逻辑代码
receiver.action();
}
}

调用这样的命令对象,感觉还不如我直接调用它的方法呢,为什么要脱掉裤子放屁,多此一举?

恭喜你,你问到命令模式的点子上去了。
命令模式分离了不同行为及其需要的信息,让行为本身(这个行为可简单可复杂)变得独立,参数化也好,动态替换也好,灵活性大大提高,我们只需要关注命令对象的实现,而且命令对象完全可以共享。
当面对多种命令对象时,不可避免的需要排队或者管理,比如线程池等,这里不做叙述。
事实上,行为对象化的需求常常就是一个简单的命令封装,不需要状态、不需要排队、不需要管理,我们可以简化一下Command:

1
2
3
4
5
6
7
public class Command implements ICommand {
@Override
public void execute(Receiver receiver) {
// 这里可以包含更多的逻辑代码
receiver.action();
}
}

Lambda表达式可以说是此类简化版本的一个极致实现了,命令模式的UML类图如下:

策略模式

定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

先看看策略模式的UML类图:

有没有发现和上面的命令模式UML类图有着高度重叠,区别在于:
命令模式强调的是对已有行为的一个封装,而策略模式强调的是一系列未知算法的替换,这些算法需要独立的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public interface IStrategy {
int doAlgorithm(int... array);
}
// 返回首元素
public class StrategyA implements IStrategy {
@Override
public int doAlgorithm(int... array) {
return array[0];
}
}
// 返回末元素
public class StrategyB implements IStrategy {
@Override
public int doAlgorithm(int... array) {
return array[array.length - 1];
}
}
public class Context {
private IStrategy strategy;
public void setStrategy(IStrategy strategy) {
this.strategy = strategy;
}
public int getData(int... array) {
// 不同的策略将会得到不同的结果
return strategy.doAlgorithm(array);
}
}

模板方法模式

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

这里的算法和策略的模式的算法都是指泛义上的算法,可以简单的理解为具体实现。
模板方法替换算法的方法最直接,就是继承覆盖,一看就懂。当然模板方法的重点是定义这些算法的结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public abstract class AbstractClass {
// 就按照这个顺序来执行
private void templateMethod() {
primitiveOperation1();
primitiveOperation2();
primitiveOperation3();
}
public void primitiveOperation1() {
}
public void primitiveOperation2() {
}
public void primitiveOperation3() {
}
}
public class ConcreteClass extends AbstractClass {
@Override
public void primitiveOperation1() {
// concrete class code
}
@Override
public void primitiveOperation2() {
// concrete class code
}
@Override
public void primitiveOperation3() {
// concrete class code
}
}

巧妙的地方(如果硬要说这里面有巧妙的话)就是templateMethod只需要挂“钩子”,而把这些钩子的具体实现延迟到子类,这在一些有固定骨架的场景下非常有用,比如生命周期等。
相比于策略模式使用组合替换算法,模板方法使用继承,UML类图如下:

小结

三个模式都很好理解,是面向对象应用的基本模式。
这几个模式都是最直接体现继承和多态特性的,虽然很简单,但却告诉大家一个道理:虽然面向对象博大精深,但万变不离其宗!

Android设计模式之命令模式、策略模式、模板方法模式的更多相关文章

  1. Android设计模式(八)--模板方法模式

    到国美面试Android的时候.问我的设计模式相关的问题: 1.单例模式的意义时什么. 2.有哪几种工厂方法模式: 3.你用过的模板方法模式.举例说明: 自己感觉答的一塌糊涂. 模板方法模式都没说出来 ...

  2. 《设计模式面试小炒》策略和工厂模式替代业务场景中复杂的ifelse

    <设计模式面试小炒>策略和工厂模式替代业务场景中复杂的ifelse 我是肥哥,一名不专业的面试官! 我是囧囧,一名积极找工作的小菜鸟! 囧囧表示:小白面试最怕的就是面试官问的知识点太笼统, ...

  3. 设计模式(二十二)模板方法模式 Template

    泡茶?泡咖啡? 我们用泡茶和泡咖啡两种行为来引入这一设计模式. 思考一下“泡茶”的过程: 煮水 -> 用沸水泡茶叶 -> 把茶倒进杯子 -> 放点柠檬之类的佐料. 然后再看一下“泡咖 ...

  4. 设计模式——Spring IoC中用到的模板方法模式

    基本概念 什么是模板方法(Template method):父类定义了骨架(调用哪些方法及顺序),某些特定方法由子类实现. 最大的好处:代码复用,减少重复代码.除了子类要实现的特定方法,其他方法及方法 ...

  5. (转)《JAVA与模式》之模板方法模式

    该文章转自:http://www.cnblogs.com/java-my-life/archive/2012/05/14/2495235.html 在阎宏博士的<JAVA与模式>一书中开头 ...

  6. 《JAVA与模式》之模板方法模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述模板方法(Template Method)模式的: 模板方法模式是类的行为模式.准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式 ...

  7. Android设计模式(十)--生成器模式

    回头看自己写的东西,大概Android当自己控制的定义,编写代码适用性比较高.但是,看看没有什么技术含量,因此,当在学习设计模式,想想有些东西是否可以改善,例如: 自己定义Dialog是Android ...

  8. Android设计模式(九)--外观模式

    问题:在Android中,Apk能够有微信,QQ为代表的插件式安装更新功能: 那么问题来了,主系统(姑且这么说)调用插件式安装的子系统.由子系统提供对外的訪问.属不属于一种外观模式呢? 先说设计模式: ...

  9. Android设计模式(七)--原型模式

    1.定义: 用原型实例指定创建对象种类,并通过拷贝这些原型创建新的对象. 2.目的: 从一个对象创建另外一个可定制的对象,而不须要知道不论什么创建细节. 3.作用: 3.1.简化对象的创建. 3.2 ...

随机推荐

  1. 汇编语言中"[]"的用法

    "[]"的用法在"常见问题"已经有所说明,引用如下: 1.push dword ptr [024c1100] 压栈024c1100值的双字 2.cmp eax, ...

  2. 客户端一个http连接包含两个方向,一个是这个http连接的输入,另一个是这个http连接的输出。

    1.客户端一个http连接包含两个方向,一个是这个http连接的输入,另一个是这个http连接的输出. 利用httpclient进行ip地址和端口号连接后,http的输出端作为http请求参数设置.h ...

  3. 关于NGUI制作图集在低内存设备上的注意事项

    正在写一个游戏.由于2D且比较简单.打算用NGUI全权搞定,对,游戏内容也用NGUI. 想的很好,做的很爽.PC上跑起来happy. 天杀的诺基亚出了个手机叫lumia520,可用内存512M.单个程 ...

  4. Hibernate逍遥游记-第3章对象-关系映射基础-access="field"、dynamic-insert、dynamic-update、formula、update=false

    1. package mypack; import java.util.*; public class Monkey{ private Long id; private String firstnam ...

  5. maven项目:Invalid bound statement

    在使用maven做mybatis项目时会遇到这个问题, org.apache.ibatis.binding.BindingException: Invalid bound statement (not ...

  6. C++:默认的构造函数

    注意:如果类中用户没有定义构造函数,系统会自动提供一个函数体为空的默认构造函数. 但是,只要类中定义了一个构造函数(不一定无参构造函数),系统将不再给它提供 默认的构造函数.因为,默认的构造函数被类中 ...

  7. linux命令-shopt

    shopt命令 shopt命令用于显示和设置shell中的行为选项,通过这些选项以增强shell易用性.shopt命令若不带任何参数选项,则可以显示所有可以设置的shell操作选项. 开启与关闭 开启 ...

  8. Flash上传文件(结合asp.net)

    一.实现原理.在某些场合,我们需要使用Flash进行“文件上传”,原因是Flash 能制作出表现力丰富的UI界面. (自负又孤陋寡闻的我在这里做一个补充:Flash使用flash.net包中的File ...

  9. Use Eclipse to develop groovy[docs.codehaus.org]

    http://docs.codehaus.org/display/GROOVY/Install+Groovy-Eclipse+Plugin http://docs.codehaus.org/displ ...

  10. c创建win窗口

    windows程序设计示例: #include "windows.h" #pragma comment(lib, "winmm") LRESULT CALLBA ...