JAVA设计模式之策略模式 - Strategy
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
介绍
什么是策略模式(Strategy Pattern)
在软件开发过程中常常遇到这样的情况, 实现某一个功能有很多种算法或实现策略, 我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能. 如果将这些算法或者策略抽象出来, 提供一个统一的接口, 不同的算法或者策略有不同的实现类, 这样在程序客户端就可以通过注入不同的实现对象来实现算法或者策略的动态替换, 这种模式的可扩展性和可维护性也更高, 这就是策略模式.
策略模式的定义(Strategy Pattern)
策略模式: 定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立与使用算法的客户.(摘抄于Head First设计模式)
简单理解: 定义了一系列算法,每个算法封装起来,各个算法之间可以互相替换,且算法的变化不会影响到使用算法的客户,属于行为型模式.
使用场景
- 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时;
- 需要安全的封装多种同一类型的操作时;
- 出现同一抽象类有多个字类, 而有需要使用 if-else 或者 switch-case 来选择具体字类时;
例如:

或出现大量 if-else 判断时可以使用策略模式优化代码.
例如电商网站支付方式,一般分为银联,微信,支付宝,可以采用策略模式,每一种方式作为一种支付方式的实现,如果哪一个支付方式发生变化,只需要修改对应的实现即可,不需要修改调用的客户端,如果引入新的支付方式,如:随行付,则只需要增加一个对应的随行付实现类即可,遵循开闭原则.
组成部分(三个角色)
1. 抽象策略(Strategy):
通常由接口或抽象类实现. 定义了多个具体策略的公共接口, 具体策略中各种不同的算法以不同的方式实现这个接口; Context使用这些接口调用不同实现的算法.
2. 具体策略(ConcreteStrategy):
实现了Strategy接口或继承与抽象类, 封装了具体的算法和行为.
3. 环境类(Context):
持有一个公共策略接口的引用(Strategy), 直接给客户端调用.
优缺点及重点
优点:
- 每个算法单独封装, 减少算法与算法调用者之间的耦合;
- 算法可以自由切换;
- 避免使用多重条件判断;
- 扩展性良好;
缺点:
- 策略类会增多.
- 所有策略类都需要对外暴露.
重点
- 给对象传入什么样的策略, 就执行什么样的动作.
实现
类图

说明: 代码来自Head First设计模式中SimUDuck的示例.
代码结构:

抽象策略(Strategy):
/**
* 飞行行为
*/
public interface FlyBehavior {
//各种飞行实现
public void fly();
}
具体策略(ConcreteStrategy):
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("I'm flying!");
}
}
环境类(Context):
/**
* 鸭子类
*/
public abstract class Duck {
//持有一个公共策略接口的引用
public FlyBehavior flyBehavior;
public QuackBehavior quackBehavior;
public void swim() {
System.out.println("我会游泳...");
}
public abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
//提供set方法, 使鸭子可以动态改变飞行策略
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
//提供set方法, 使鸭子可以动态改变叫声策略
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
/**
* 绿头鸭
*/
public class MallardDuck extends Duck {
@Override
public void display() {
System.out.println("绿头鸭");
}
public MallardDuck() {
/*MallardDuck 继承 Duck, 所以具有quackBehavior 和 flyBehavior实例变量
当MallardDuck实例化时, 它的构造器会把继承的quackBehavior,
flyBehavior实例变量初始化成Quack,FlyWithWings类型的新实例
*/
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
}
测试类:
public static void main(String[] args) {
Duck mallard = new MallardDuck();
//飞行
mallard.performFly();
//改变鸭子行为(传入飞行策略)
mallard.setFlyBehavior(new FlyRocketPowered());
mallard.performFly();
//叫声
mallard.performQuack();
}
执行结果:
I'm flying!
I'm flying with a rocket!
呱呱叫
生活中的策略模式(我的猜想)
俗话说: 人是铁饭是钢, 一顿不吃饿的慌;吃饭也有策略模式, 你晓得嘛.
人(环境类)饿了要吃饭(抽象策略), 但是吃什么你知道吗? 这时你的大脑就会调集你的毕生功力(经验, 生活经历, 常识等等),来知道有哪些东西是可以吃的,比如鸡腿,面包或粥等等(具体策略,暴露所有策略).大脑选择(动态选择策略)吃其中的一种或多种食物来应对身体的不满.
生活中这样的例子还有很多,网上购物(不同的商品即: 具体策略), 世界那么大, 我想去转转.(转转的方式即: 具体策略)等.
结语
设计模式源于生活
JAVA设计模式之策略模式 - Strategy的更多相关文章
- 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)
原文:乐在其中设计模式(C#) - 策略模式(Strategy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 策略模式(Strategy Pattern) 作者:webabc ...
- Java设计模式之策略模式(Strategy)
前言: 最近一直在学习基于okHttp网络请求,学习的过程中就想起了之前项目中有这么一个需求不同的接口要采用不同的加密方式,比如登录之前要采用RSA加密,登录之后要采用AES加密,当时是采用靠传递一个 ...
- 反馈法学习设计模式(一)——策略模式Strategy Pattern
简介(Introduction) 之前学习Java8实战时,遇到一个很好的策略模式示例.便想着借着这个示例结合反馈式的方法来,学习策略设计模式,也以便后面反复琢磨学习. 首先我们通过练习,逐步写出符合 ...
- 8.6 GOF设计模式四: 策略模式… Strategy Pattern
策略模式… Strategy Pattern 在POS系统中,有时需要实行价格优惠, 该如何处理? 对普通客户或新客户报全价 对老客户统一折扣5% 对大客户统一折扣10% 注:课件 ...
- 二十四种设计模式:策略模式(Strategy Pattern)
策略模式(Strategy Pattern) 介绍定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换.本模式使得算法的变化可独立于使用它的客户. 示例有一个Message实体类,对它的操作有 ...
- Java设计模式1——策略模式(Strategy Pattern)
最近觅得一本好书<您的设计模式>,读完两章后就能断言,一定是一头极品屌丝写的,而且是专写给开发屌丝男的智慧枕边书,小女子就委屈一下,勉强看看,人笨,谁让他写得这么通俗易懂呢!为了加深理解, ...
- JAVA设计模式一策略模式(Strategy Pattern)
什么是设计模式? 就是一些经验.让程序代码更具弹性.好维护.代码复用的经验.而且设计模式都遵从一些OO设计原则. 题外话:以下罗列出常用的OO设计原则:链接 本文章介绍策略模式(Strategy Pa ...
- Java设计模式之策略模式(Strategy Pattern)
简介 策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 组成 1.抽象策略角色(Strategy): 策略类,通常由一个接口或者抽象类实现. 2.具 ...
- 折腾Java设计模式之策略模式
博客原文地址 简介 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式.简单理解就是一组算法,可以互换,再简单点策略就是封装算法. ...
随机推荐
- codevs 1154 能量项链
传送门 1154 能量项链 2006年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在Mars星 ...
- for循环的一个注意点
unsigned int i =10; for(i;i > 0; i--) { xxxxx } 因为i是unsigned int 类型的,永远不可能小于0,也就是说是个死循环了.
- zlog日志库的简单封装,以及给debug级别添加颜色显示
现看看效果如何: 方法如下: 定义相关颜色的宏 #define ESC_START "\033[" #define ESC_END "\033[0m" #def ...
- 2.row_number() over (partition by col1 order by col2)的用法
row_number() over (partition by col1 order by col2) 表示根据COL1分组,在分组内部根据 COL2排序,而此函数计算的值就表示每组内部排序后的顺序编 ...
- .NET Framework4网站 无法运行,提示找不到网络名,IO错误等解决办法
.NET Framework4网站 无法运行,提示找不到网络名,IO错误等解决办法 我的这个问题解决了,原因是用的远程桌面连接的服务器, 远程桌面中部署网站的文件夹,引用的竟然是连接此服务器的用户的电 ...
- Struts文件上传下载
Struts配置文件: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PU ...
- HDOJ-2037
今年暑假不AC Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Sub ...
- 【网络爬虫】【python】网络爬虫(四):scrapy爬虫框架(架构、win/linux安装、文件结构)
scrapy框架的学习,目前个人觉得比较详尽的资料主要有两个: 1.官方教程文档.scrapy的github wiki: 2.一个很好的scrapy中文文档:http://scrapy-chs.rea ...
- linux常用命令的全拼
Linux常用命令英文全称与中文解释Linux系统 Linux常用命令英文全称与中文解释linux系统 man: Manual 意思是手册,可以用这个命令查询其他命令的用法. pwd:Print ...
- 模拟定位工具gps mock
1. 到应用宝下载http://sj.qq.com/myapp/detail.htm?apkName=com.lexa.fakegps 2. 在 setting 里面 开发者选项 3. 把 模 ...