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

命令模式

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

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. Castle 开发系统文章

    转: http://www.cnblogs.com/Jebel/archive/2008/06/24/1228766.html

  2. 微软发布WP SDK8.0 新增语音、应用内支付等原生API

    http://www.csdn.net/article/2012-10-31/2811338-windows-phone-8-sdk 京时间10月30日,微软在旧金山举行新一代手机操作系统Window ...

  3. git安装及使用

    一.安装 1.从http://code.google.com/p/msysgit/下载Git-1.8.4-preview20130916.exe,并安装. 2.新建git目录,右键选择Git Bash ...

  4. prim求MST

    PRIM==>>MST模板 #include <iostream> using namespace std; #define typec int #define V 3 con ...

  5. windows service 安装和卸载指令

    添加服务: cd C:\Windows\Microsoft.NET\Framework\v4.0.30319InstallUtil.exe D:\OneKeyWebSiteDeployment\Ser ...

  6. poj 2485 Highways(最小生成树,基础,最大边权)

    题目 //听说听木看懂之后,数据很水,我看看能不能水过 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stri ...

  7. js注册验证【转】

    function getFocus() //设置用户名文本框获取焦点 { document.getElementById("txtuname").focus(); } functi ...

  8. PHP WAMP关闭notice等提示

    这是xdebug的的错误报告.在开发环境下,可以考虑将其开启,但是在部署到真实应用环境下应该将其关掉. 找到你的php.ini 在最后几行注释掉所有关于xdebug的东西,重启apache即可!

  9. c# 在windows服务中 使用定时器

    由于最近做自动执行的程序,开始做windows服务程序, 在windows服务中如何使用定时器的时候一直失效, 以前是直接拖入timer控件,但是不能直接运行,后来在网上找了一段程序,好使了. //开 ...

  10. cojs EX_香蕉 题解报告

    这道题目是香蕉的加强版 当m=100w时矩阵会很大,而且又有多组询问,所以这道题用原来香蕉的程序会T 所以我们需要更好点的做法 我们考虑优化我们的状态 首先考虑这道题的隐藏性质,考虑不合法的情况 那么 ...