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

命令模式

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

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. 【Android自学之旅】 Android开发环境的搭建

    [Android自学之旅] Android开发环境的搭建 搭建参考教程: http://www.oracle.com/technetwork/java/javase/downloads/jdk7-do ...

  2. hdu 4901

    一个简单的dp,比赛的时候太坚信自己的小聪明没用二维数组一直WA到死: #include<cstdio> #include<cstring> #define maxn 1009 ...

  3. 11个实用jQuery日历插件

    1. FullCalendar FullCalendar是很出名的jQuery日历插件,它支持拖拽等功能,整合了Google Calendar,而且可以通过JSON来绑定事件,设计师可以轻松地自定义日 ...

  4. Spring Boot——2分钟构建spring web mvc REST风格HelloWorld

    之前有一篇<5分钟构建spring web mvc REST风格HelloWorld>介绍了普通方式开发spring web mvc web service.接下来看看使用spring b ...

  5. addListener添加事件监听器,第三个参数useCapture (Boolean) 的作用

    addEventListener 有三个参数:第一个参数表示事件名称(不含 on,如 "click"):第二个参数表示要接收事件处理的函数:第三个参数为 useCapture,本文 ...

  6. [杂题]HDOJ5515 Game of Flying Circus

    嗯...这是一道水题... 鉴于还没人写这题的题解, 那我就来写一发. 题意:有个边长为300米的正方形 嗯  这样标号 有两个人A和S,开始的时候A.S都在1(左下角)那个位置. 两个人都要按照2. ...

  7. 关于inline-block在IE8下无效的解决方法

    <style> .divClass{ width:500px; border:1px solid #ccc; } /*IE8下可以不用加(*zoom:1;*display:inline;需 ...

  8. 【PHPsocket编程专题(实战篇②)】兼容 Curl/Socket/Stream 的 HTTP 操作类[转]

    <?php /************************************************************ * 描述:HTTP操作类 * 作者:heiyeluren ...

  9. linux软中断与硬中断实现原理概述

    linux软中断与硬中断实现原理概述. 1.软中断通过open_softirq注册一个软中断处理函数,即在软中断向量表softirq_vec数组中添加新的软中断处理action函数. 2.调用rais ...

  10. 理解maven

    1.理解“仓库” 首次运行完mvn -version后,会在用户目录下创建一个.m2的目录(比如:C:\Users\当前用户名\.m2\),这个目录是maven的“本地仓库”,仓库是maven中一个很 ...