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

命令模式

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

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. mysql 。。。

    MySQL的相关概念介绍 MySQL 为关系型数据库(Relational Database Management System), 这种所谓的"关系型"可以理解为"表格 ...

  2. python参考手册--第1章python简介

    1.if __name__ == '__main__': 直接运行myModel.py时,当前模块的名字是main:import myModel然后运行的时候当前模块的名字是myModel. 2.ev ...

  3. hdu 1195 Open the Lock(广搜,简单)

    题目 猜密码,问最少操作多少次猜对,思路很简单的广搜,各种可能一个个列出来就可以了,可惜我写的很搓. 不过还是很开心,今天第一个一次过了的代码 #define _CRT_SECURE_NO_WARNI ...

  4. 一些linux的问题

    本文罗列的是我在学习linux与shell编程时所遇到的一些问题.我相信既然存在问题那么就会有需求,记录于此,希望可以快速帮助到大家. 1.在vim中用“/word"查找后,vim会以棕色背 ...

  5. maven_Error building POM (may not be this project's POM)错误

    如果maven项目在执行编译等操作时报如题错误的话,请仔细检查pom.xml,一般是由pom的语法错误导致的,例如我的项目是因为: dependencies 元素下不应该有properties元素导致 ...

  6. lintcode :sort letters by case字符大小写排序

    题目 字符大小写排序 给定一个只包含字母的字符串,按照先小写字母后大写字母的顺序进行排序. 您在真实的面试中是否遇到过这个题? Yes 样例 给出"abAcD",一个可能的答案为& ...

  7. lintcode: 翻转链表

    题目: 翻转链表 翻转一个链表 样例 给出一个链表1->2->3->null,这个翻转后的链表为3->2->1->null 挑战 在原地一次翻转完成 解题: 递归还 ...

  8. hdu 3544 Alice's Game

    #include<stdio.h> int main() { int t,n; __int64 sum1,sum2; int i,j,a,b; scanf("%d",& ...

  9. GDB笔记

    GDB是在Linux命令行下对C/C++的程序进行调试常用的一个命令,现将平时记录在本子上的笔记整理如下: 一.断点 断点类型有breakpoints, watchpoints, catchpoint ...

  10. [hackerrank]Closest Number

    https://www.hackerrank.com/contests/w5/challenges/closest-number 简单题. #include <iostream> #inc ...