Strategy策略设计模式
1、策略模式和状态模式的区别和联系(本部分转载自:http://letscoding.cn/java%E4%B8%AD%EF%BC%8C%E7%8A%B6%E6%80%81%E6%A8%A1%E5%BC%8F%E5%92%8C%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F%E7%9A%84%E5%8C%BA%E5%88%AB/)
策略模式通过封装一组相关算法,为Client提供运行时的灵活性。Client可以在运行时,选择任一算法,而不改变使用算法的Context。一些流行的策略模式的例子是写那些使用算法的代码,例如加密算法、压缩算法、排序算法。另一方面,状态模式允许对象,在不同的状态拥有不同的行为。因为现实世界中的对象通常都是有状态的,所以它们在不同状态,行为也不一样。例如,VM(自动售货机)只在hasCoin状态才给你吐商品;你不投币,它是不会吐的。现在你可以清楚的看出它们的不同之处了:它们的意图是不同的。状态模式帮助对象管理状态,而策略模式允许Client选择不同的行为。
另一个不那么容易能看出来的区别是:是谁促使了行为的改变。策略模式中,是Client提供了不同的策略给Context;状态模式中,状态转移由Context或State自己管理。另外,如果你在State中管理状态转移,那么它必须持有Context的引用。例如,在VM的例子中,State对象需要调用VM的setState()方法去改变它的状态。另一方面,Strategy从不持有Context的引用,是Client把所选择的Strategy传递给Context。由于状态模式和策略模式的区别,是流行的Java设计原则类面试题之一,我们将会在本文探讨在Java中,状态模式和策略模式的异同,这可以加深你对它们的理解。
相似之处
如果你看看状态模式和策略模式的UML图,就会发现它们的结构非常相似。使用State对象改变自己行为的对象被称为Context对象;相似的,使用Strategy对象改变自己行为的对象叫Context对象。记住,Client和Context打交道。在状态模式中,Context把方法调用委托给当前的状态对象,而在策略模式中,Context使用的Strategy对象,是被当做参数传递过来的,或在Context对象被创建时就被提供的。
让我们来看看它们之间更多的相似之处:
- 添加新的状态或策略都很容易,而且不需要修改使用它们的Context对象。
- 它们都让你的代码符合OCP原则。在状态模式和策略模式中,Context对象对修改是关闭的,添加新的状态或策略,都不需要修改Context。
- 正如状态模式中的Context会有初始状态一样,策略模式同样有默认策略。
- 状态模式以不同的状态封装不同的行为,而策略模式以不同的策略封装不同的行为。
- 它们都依赖子类去实现相关行为。
不同之处
现在我们知道,状态模式和策略模式的结构是相似的,但它们的意图不同。让我们重温一下它们的主要不同之处:
- 策略模式封装了一组相关算法,它允许Client在运行时使用可互换的行为;状态模式帮助一个类在不同的状态显示不同的行为。
- 状态模式封装了对象的状态,而策略模式封装算法或策略。因为状态是跟对象密切相关的,它不能被重用;而通过从Context中分离出策略或算法,我们可以重用它们。
- 在状态模式中,每个状态通过持有Context的引用,来实现状态转移;但是每个策略都不持有Context的引用,它们只是被Context使用。
- 策略实现可以作为参数传递给使用它的对象,例如Collections.sort(),它的参数包含一个Comparator策略。另一方面,状态是Context对象自己的一部分,随着时间的推移,Context对象从一个状态转移到另一个状态。
- 虽然它们都符合OCP原则,策略模式也符合SRP原则(单一职责原则),因为每个策略都封装自己的算法,且不依赖其他策略。一个策略的改变,并不会导致其他策略的变化。
- 另一个理论上的不同:策略模式定义了对象“怎么做”的部分。例如,排序对象怎么对数据排序。状态模式定义了对象“是什么”和“什么时候做”的部分。例如,对象处于什么状态,什么时候处在某个特定的状态。
- 状态模式中很好的定义了状态转移的次序;而策略模式并无此需要:Client可以自由的选择任何策略。
- 一些常见的策略模式的例子是封装算法,例如排序算法,加密算法或者压缩算法。如果你看到你的代码需要使用不同类型的相关算法,那么考虑使用策略模式吧。而识别何时使用状态模式是很简单的:如果你需要管理状态和状态转移,但不想使用大量嵌套的条件语句,那么就是它了。
- 最后但最重要的一个不同之处是,策略的改变由Client完成;而状态的改变,由Context或状态自己。
本段译自:Difference between State and Strategy Design Pattern in Java
2、URL图下载地址(astah/jude):http://pan.baidu.com/s/1hqy0c88

3、示例
公共策略规范接口
package com.xinye.test.strategy;
/**
* 策略通用接口
* @author xinye
*
*/
public interface IStrategy {
public void strategy();
}
默认策略
package com.xinye.test.strategy;
/**
* 默认Strategy
* @author xinye
*
*/
public class NormalStrategy implements IStrategy { @Override
public void strategy() {
System.out.println(getClass().getSimpleName() + " strategy()");
} }
第一种策略
package com.xinye.test.strategy;
/**
* 第一种Strategy
* @author xinye
*
*/
public class FirstStrategy implements IStrategy { @Override
public void strategy() {
System.out.println(getClass().getSimpleName() + " strategy()");
} }
第二种策略
package com.xinye.test.strategy;
/**
* 第二种Strategy
* @author xinye
*
*/
public class SecondStrategy implements IStrategy { @Override
public void strategy() {
System.out.println(getClass().getSimpleName() + " strategy()");
} }
策略Context
package com.xinye.test.strategy;
/**
* 策略模式Context
* @author xinye
*
*/
public class Context { private IStrategy strategy = new NormalStrategy();
/**
* 需要客户端把策略传递过来
* @param s
*/
public void exec(IStrategy s){
strategy = s;
strategy.strategy();
}
}
客户端代码
package com.xinye.test.strategy;
/**
* 客户端代码
* @author xinye
*
*/
public class Client {
public static void main(String[] args) { Context context = new Context();
// 传递给Context特定的策略
context.exec(new NormalStrategy());
// 传递给Context特定的策略
context.exec(new FirstStrategy());
// 传递给Context特定的策略
context.exec(new SecondStrategy());
}
}
执行结果
NormalStrategy strategy()
FirstStrategy strategy()
SecondStrategy strategy()
Strategy策略设计模式的更多相关文章
- Java的设计模式----strategy(策略模式)
设计模式: 一个程序员对设计模式的理解: “不懂”为什么要把很简单的东西搞得那么复杂.后来随着软件开发经验的增加才开始明白我所看到的“复杂”恰恰就是设计模式的精髓所在,我所理解的“简单”就是一把钥匙开 ...
- 设计模式(21)--Strategy(策略模式)--行为型
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.模式定义: 策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而 ...
- 设计模式22:Strategy 策略模式(行为型模式)
Strategy 策略模式(行为型模式) 动机(Motivation) 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂:而且有时候支持 ...
- 一天一个设计模式——Strategy策略模式
一.模式说明 策略模式比较好理解,就是将程序中用到的算法整体的拿出来,并有多个不同版本的算法实现,在程序运行阶段,动态的决定使用哪个算法来解决问题. 举个实际的例子:排序算法的问题,假如我们的程序中需 ...
- C++设计模式-Strategy策略模式
Strategy策略模式作用:定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. UML图: Strategy模式将逻辑(算法)封装到一个类(Cont ...
- Java设计模式之策略设计模式
1.什么是-策略设计模式 在软件开发中常常遇到这种情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查找.排序等,一种常用的方法是硬编码(Ha ...
- java策略设计模式
1.概述 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,让算法独立于使用它的客户而独立变化. 其实不要被晦涩难懂的定义所迷惑,策略设计模式实际上就是定义一个接口,只要实现 ...
- JAVA学习笔记--策略设计模式与适配器模式
一.策略设计模式 创建一个能够根据所传递对象的不同而具有不同行为的方法被称为策略设计模式:这类方法包含所要执行的算法中固定不变的部分,而“策略”包含变化的部分.策略就是传递进去的参数对象,它包含要执行 ...
- 10、Strategy 策略模式 整体地替换算法 行为型模式
1.模式说明 策略模式比较好理解,就是将程序中用到的算法整体的拿出来,并有多个不同版本的算法实现,在程序运行阶段,动态的决定使用哪个算法来解决问题. 2.举例 排序算法的问题,假如我们的程序中需要对数 ...
随机推荐
- commons-logging和log4j
1.Apache通用日志接口(commons-logging.jar)介绍 Apache Commons包中的一个,包含了日志功能,必须使用的jar包.这个包本身包含了一个Simple Logger, ...
- swoole 安装
swoole 安装: 1. 下载源代码,我下载的是1.8.6版本wget https://github.com/swoole/swoole-src/archive/1.8.6-stable.tar.g ...
- python文件选择:tkFileDialog 基础
tkFileDialog有两种形式: 一个是.askopenfilename(option=value, ...) 这个是"打开"对话框 另一个是:asksaveasfilenam ...
- linux-8 基本命令---echo
1.echo 命令用于终端显示字符或变量 格式:“echo[字符串| 变量]” @1 .echo命令的字符串输出到终端: @2 .echo查看当前SHELL的变量值(前面有$符号): @3 .查看 ...
- innodb_ft_max_token_size取值范围
根据问档中所说,innodb_ft_max_token_size取值范围为10-252,而实际上但我们在配置文件设置innodb_ft_max_token_size=252时,error log会出现 ...
- 从Java看跨平台的.NET需要些什么?
跨平台的运行时(Runtime):JRE(JVM) -> .NET Core CLR . 跨平台的编译器(Compiler):javac -> Roslyn [github.com/d ...
- IIS问题解决:URL中制表符引起的Bad Request - Invalid URL
昨天处理好了Google网站管理员中的500错误,今天处理了一些400处理,比如下面的以制表符(tab)结尾的URL: http://www.cnblogs.com/me-sa/archive/200 ...
- Excel Interactive View - 让页面表格的功能更强大
MS Office Excel Services提供了一个非常强大的功能,允许你只需要在页面上添加非常少量的JS references,就可以让你在页面上将表格的内容以Excel图表的方式呈现.这里是 ...
- atitit.为什么java体系开发效率这样低的原因and解决
atitit.为什么java体系开发效率这样低的原因and解决 #---开发理念问题(影响度:很大的,2-3倍效率) mvc<>webform server control ajax< ...
- paip.取当天记录的方法sql跟hql hibernate
paip.取当天记录的方法sql跟hql hibernate #------两个方法...函数法和日期计算法.. 函数法: DATEDIFF(d,createTime,GETDATE())=0 / ...