我的Java设计模式-策略模式
今天给大家说说田忌赛马的故事。如有雷同,纯属巧合!话说在战国时期,群雄割据,硝烟四起,茶余饭后还是少不了娱乐活动的,其中赛马是最火爆的。一天,孙膑看到田忌像个死鸡似的就知道肯定赛马又输给了齐威王,立马抓住田忌去跟齐威王再赛一场。
孙膑:“小忌啊,哥哥看着你心疼啊,哥哥出对策帮你赢一盘如何?”。
田忌听到之后高兴得飞起,瞪大了两只金鱼眼“Really?只要能赢,我赴汤蹈火,以身相许又如何~”。
孙膑心里一万个草泥马在奔腾,差点没噎死自己“滚一边去,我们这盘跟他show hand!”赛马开始,策略模式上场。此处应该有bgm“让我们红尘作伴活得潇潇洒洒 策马奔腾共享人世繁华...呀啊呀啊,呀啊啊啊啊啊啊~”
一、策略模式
定义
定义一组算法,将每一个算法封装起来,从而使它们可以相互切换。
特点
1)一组算法,那就是不同的策略。
2)这组算法都实现了相同的接口或者继承相同的抽象类,所以可以相互切换。
UML
策略模式涉及到的角色有三个:
- 封装角色:上层访问策略的入口,它持有抽象策略角色的引用。
- 抽象策略角色:提供接口或者抽象类,定义策略组必须拥有的方法和属性。
- 具体策略角色:实现抽象策略,定义具体的算法逻辑。
二、实战
在跟齐威王比赛之前来分析下之前输掉比赛的“策略”,首先来看封装角色,代码如下:
public class Context {
private Strategy strategy;
/**
* 传进的是一个具体的策略实例
* @param strategy
*/
public Context(Strategy strategy) {
this.strategy = strategy;
}
/**
* 调用策略
*/
public void contextInterface() {
strategy.algorithmLogic();
}
}
Context持有Strategy的引用,并且提供了调用策略的方法,很清晰。
再来抽象策略角色,定义了策略组的方法,代码如下:
public interface Strategy {
public void algorithmLogic();
}
输掉比赛的“策略”也是一种策略,是具体策略角色类,来看代码:
public class ConcreteStrategyA implements Strategy{
@Override
public void algorithmLogic() {
// 具体的算法逻辑(输了比赛)
System.out.println("第一场:上等马vs上等马 第二场:中等马vs中等马 第三场:下等马vs下等马 赛果:输!");
}
}
看到这里,孙膑一阵无语,惨不忍睹也得看结果的,客户端代码如下:
public class Client {
public static void main(String[] args) {
// 操控比赛,这场要输
Context context = new Context(new ConcreteStrategyA());
context.contextInterface();
}
}
两句代码,传入具体策略对象,调用策略入口方法,运行结果如下:
第一场:上等马vs上等马 第二场:中等马vs中等马 第三场:下等马vs下等马 赛果:输!
田忌跟孙膑说:“膑哥,我怕!”,孙膑:“不用怕,哥哥在!”。
田忌找到齐威王“大王,我们再...再再来一盘,输了请吃饭”
瞅瞅孙膑出的策略,一睹军事家的风采,“赢”的具体策略类代码如下:
public class ConcreteStrategyB implements Strategy{
@Override
public void algorithmLogic() {
// 赢
System.out.println("第一场:下等马vs上等马 第二场:上等马vs中等马 第三场:中等马vs下等马 赛果:赢!");
}
}
再来看客户端的代码:
public class Client {
public static void main(String[] args) {
// 操控比赛,这场要赢,哈哈哈
Context context = new Context(new ConcreteStrategyB());
context.contextInterface();
}
}
运行结果如下:
第一场:下等马vs上等马 第二场:上等马vs中等马 第三场:中等马vs下等马 赛果:赢!
田忌拍烂手掌,重要的是今天晚饭有着落了,还要对膑哥哥以身相许的......
三、策略模式的优缺点
优点
1)良好的扩展性。增加一种策略,只要实现接口,写上具体逻辑就可以了。当旧策略不需要时,直接剔除就行。
2)良好的封装性。策略的入口封装在Context封装类中,客户端只要知道使用哪种策略就传哪种策略对象就可以了。
3)避免了像简单工厂模式这样的多重条件判断。
缺点
1)客户端必须了解策略组的各个策略,并且决定使用哪一个策略,也就是各个策略需要暴露给客户端。
2)如果策略增多,策略类的数量就会增加。
四、扩展
上面说到策略模式有一个缺点,就是所有的策略都必须暴露出去,让客户端自行选择策略使用。现在来改善这一缺陷,而改善这个缺陷需要跟简单工厂模式结合混编,继续往下看。
当然,军事家孙膑也会想到这一点,怎么可能会把自己的套路全都暴露给别人呢,那还怎么玩是吧。不过,历史上并没有说孙膑改善了这点,现在是我来改善这个缺陷,哈哈哈~
策略工厂
思考一个问题,策略暴露了,改善就是把策略隐藏起来,而工厂模式就有这个效果,客户端不需要知道策略具体是什么,只知道结果就好。OK,那么我们可以使用工厂模式把策略当做产品生成吗?答案是肯定的。策略模式的入口就在Context封装类,可以从这个角色做手脚。先看代码:
public class Context {
private Strategy strategy;
// 把创建策略放在封装角色内,客户端只需要知道结果
public void factory(String strategyType) {
if (strategyType.equals("WIN")) {
strategy = new ConcreteStrategyB();
} else if (strategyType.equals("LOSE")) {
strategy = new ConcreteStrategyA();
}
}
/**
* 调用策略
*/
public void contextInterface() {
strategy.algorithmLogic();
}
}
代码很简单,增加了factory的方法,这个方法作用就是创建策略对象。这样,客户端就不需要去理解具体的策略,只需知道具体策略的结果就好。看看客户端代码:
public class Client {
public static void main(String[] args) {
Context context = new Context();
context.factory("LOSE");
context.contextInterface();
}
}
总结
注意策略模式和工厂方法模式的区别,在前面工厂方法模式中有说到,这里就不再阐述。策略模式本身也相对比较简单,重点在它的扩展以及其它模式的对比,分析各自的优缺点。来看看策略工厂这样的模式存在缺点吗?很明显,如果需要添加或者淘汰一种策略,Context就必须修改,这并不符合开闭原则。在《设计模式之禅》中的提出通过策略枚举和反射机制对策略模式进行改良,膜拜了~但是要添加或淘汰策略,还是得去对枚举进行修改,也不符合开闭原则。根据自己项目情况,选择最适合自己项目的模式。下一篇是责任链模式,欢迎继续关注,goodbye!
设计模式Java源码GitHub下载:https://github.com/jetLee92/DesignPattern
我的Java设计模式-策略模式的更多相关文章
- java设计模式 策略模式Strategy
本章讲述java设计模式中,策略模式相关的知识点. 1.策略模式定义 策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户.策略模式属于对象的 ...
- JAVA 设计模式 策略模式
用途 Title 它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. 策略模式是一种行为型模式. 结构
- Java设计模式-策略模式详解
前言 在软件领域中,设计模式作为一种经典的开发实践常常需要我们去深入的理解,而策略模式作为设计模式的一种,使用频率也是相对来说比较高的,在Java中,当我们学习TreeSet集合的时候,就采用了经典的 ...
- Java设计模式—策略模式
1.策略模式(Strategy Pattern)是一种比较简单的模式,也叫做政策模式(PolicyPattern). 定义如下: Define a family of algorithms,e ...
- Java 设计模式--策略模式,枚举+工厂方法实现
如果项目中的一个页面跳转功能存在10个以上的if else判断,想要做一下整改 一.什么是策略模式 策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理,最终可以实现解决 ...
- java设计模式--策略模式
策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换.策略模式使得算法可以在不影响到客户端的情况下发生变化. 本文地址:http:// ...
- Java设计模式-策略模式(strategy)
策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户.需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无 ...
- Java设计模式——策略模式
策略模式的定义: 策略模式其实特别好理解,俗话说得好,条条大路通罗马,做的都是一件事,实现的方式却可以千万种,在这种情况下,如何使得每个人都可以根据自己的喜好来选择具体的方式,在调用时可以根据不同方式 ...
- Java设计模式-策略模式实际应用场景
容错恢复机制 容错恢复机制是应用程序开发中非常常见的功能.那么什么是容错恢复呢?简单点说就是:程序运行的时候,正常情况下应该按照某种方式来做,如果按照某种方式来做发生错误的话,系统并不会 ...
随机推荐
- kickstart无人值守
笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 高逼格装系统的方法 Kickstar Cobbler 注意,kickstart并不是一个服务的名称,只是装系统的方 ...
- 【转】GPS基线解算模式
GPS基线向量是利用2台或2台以上GPS接 收机所采集的同步观测数据形成的差分观测值,通过参数估计得方法所计算出的两两接收机间的三维坐标差.与常规地面测量中所测定的基线边长不同,基线向量是 既具有长度 ...
- DVWA安装问题(phpStudy)
安装过程出现的问题: 1.PHP function allow_url_include disabled 注意DVWA的版本 PHP version: 5.4.45 打开/phpStudy/ph ...
- SDK,API概念
什么是SDK什么是API? SDK 就是 Software Development Kit 的缩写,就是"软件开发工具包". 这是一个覆盖面相当广泛的名词,可以这么说:辅助开发某一 ...
- 自己做的notepad++ FTP同步插件
平时修改FTP上的文件的时候,想先备份一下,没有合适的方法,尝试做了一个小插件. 差点忘了,下载地址 https://pan.baidu.com/s/1htdtT9E 下面是 具体的说明 Fa ...
- @RequestMapping注解
Spring MVC中用于参数绑定的注解有很多,都在org.springframework.web.bind.annotation包中,根据它们处理的request的不同内容部分可以分为四类(主要讲解 ...
- 【java学习】spring mvc 公共dao的实现,定义基本的增删改查
接口类: package com.blog.db.dao; import com.blog.util.Pagination; import java.util.List; public interfa ...
- log4j源码解析-文件解析
承接前文log4j源码解析,前文主要介绍了log4j的文件加载方式以及Logger对象创建.本文将在此基础上具体看下log4j是如何解析文件并输出我们所常见的日志格式 附例 文件的加载方式,我们就选举 ...
- Python基础篇(四)
Python中的字典类似于Java中的Map,数据以键值对的形式存储. 字典可以用以下的方式使用: >>> phonebook = {"alice":" ...
- HDU 5996 dingyeye loves stone [阶梯Nim]
dingyeye喜欢和你玩石子游戏. dingyeye有一棵nn个节点的有根树,节点编号为00到n−1n−1,根为00号节点.游戏开始时,第ii个节点上有a[i]a[i]个石子.两位玩家轮流操作,每次 ...