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

命令模式

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

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. uva 10617

    当s[i] = s[j]   dp[i][j] = 1+dp[i+1][j-1]+dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1] = 1+dp[i][j-1]+dp[i+1][j ...

  2. unity调用MMBilling_2.4.2 Android SDK.

    原地址:http://www.cnblogs.com/ayanmw/p/3736284.html 项目要使用android 的移动支付SDK 应用内付费[http://dev.10086.cn/wik ...

  3. poj 2031 Building a Space Station(最小生成树,三维,基础)

    只是坐标变成三维得了,而且要减去两边的半径而已 题目 //最小生成树,只是变成三维的了 #define _CRT_SECURE_NO_WARNINGS #include<stdlib.h> ...

  4. C#接口的经典案例

    C#接口(interface)实例子(简单而经典)2008/12/04 10:04using System; using System.Collections.Generic; using Syste ...

  5. POJ1789Truck History

    题意 : 说实话,题意我没看懂,后来让人给我讲的样例..... 4 aaaaaaa baaaaaa abaaaaa aabaaaa 0 这个样例的话,就是输入n下面n行,每行7个字母,让你依次选两行进 ...

  6. VBS生成随机数

    自动化工作中常常遇到因数据重复使业务无法提交的问题,我想到了利用随机数来解决这个问题,下面对VBS生成随机数做下解析: 一.Randomize语句 Randomize :初始化随机数生成器. 语法 : ...

  7. http://blog.csdn.net/superhosts/article/details/15813247

    http://blog.csdn.net/superhosts/article/details/15813247

  8. lintcode :nth to Last Node In List 链表倒数第n个节点

    题目: 链表倒数第n个节点 找到单链表倒数第n个节点,保证链表中节点的最少数量为n. 样例 给出链表 3->2->1->5->null和n = 2,返回倒数第二个节点的值1. ...

  9. Android系统

    系统内核 Android 是运行于Linux kernel之上,但并不是GNU/Linux.   因为在一般GNU/Linux 里支持的功能,Android 大都没有支持,包括Cairo.X11.Al ...

  10. Could not connect to SMTP host: smtp.***.com, port: 465, response: -1

    背景 在使用javamail进行邮件发送的时候,报错: Could not connect to SMTP host: smtp.***.com, port: 465, response: -1 原因 ...