简介

策略属于行为型模式的一种,策略模式允许对象的行为或算法在运行时改变,使用不同的算法达成相同的结果或目的.

实现层面上,定义一个抽象的算法接口, 然后根据具体算法的不同定义不同的类去实现该接口, 调用时不同实现的实例可以相互替换.

策略模式适用于多个类只有行为不同,运行时根据上下文决定使用哪种行为; 根据实际情况不同算法可能不同, 或算法的最优实现在未来确定.

意图

定义一系列算法,封装每个算法,并使它们可以互换。

类图

实现

以绝地求生游戏为例, 要想赢得最后的比赛可能由多种方式(策略), 抽象出 策略接口 WinStrategy, 实现策略 比如激进点的方式AlwaysKillWinStrategy,猥琐点的方式AlwaysHideWinStrategy.

下面我们将实现策略模式(一,二,三步), 并最后讨论更具实际意义的策略与上下文通信的两种方式及其各自利弊(四).

一. 定义策略接口

/**
* 赢得吃鸡的策略接口
*/
public interface WinStrategy {
void win();
}

二. 实现策略,使用两种不同的算法实现

/**
* 采用人挡杀人的模式
*/
public class AlwaysKillWinStrategy implements WinStrategy {
public void win() {
System.out.println("总是很钢,大杀四方");
}
} /**
* 采用LYB的模式
*/
public class AlwaysHideWinStrategy implements WinStrategy {
public void win() {
System.out.println("总是很苟,活得长久");
}
}

三. 调用

public class StrategyTest {
public static void main(String[] args) {
WinStrategy iWillWin = new AlwaysHideWinStrategy();
iWillWin.win();
iWillWin = new AlwaysKillWinStrategy();
iWillWin.win();
} }

四. 策略与上下文

上面的例子中我们并没有体现出上下文的概念, 其隐藏的上下文在main()函数中. 除了 策略接口实现策略 外, 还需要一个 策略上下文 角色.一般由上下文持有策略的引用, 并对策略进行实际调用,下面的代码定义该角色

/**
* 上下文
*/
public class Context { private String weather;
WinStrategy winStrategy; public Context(String weather, WinStrategy winStrategy) {
this.weather = weather;
this.winStrategy = winStrategy;
} public void winGame() {
winStrategy.win();
System.out.println("天气情况:"+this.weather+"; 采用的策略:"+winStrategy.getClass());
} } //调用
public class StrategyTest {
public static void main(String[] args) {
WinStrategy iWillWin = new AlwaysHideWinStrategy();
Context context = new Context("雾天",iWillWin);
context.winGame();
}
}

策略中有时候也需要某些上下文信息, 例如win()方法需要游戏场景中的天气情况, 这种情况下可以将上下文引用传入策略, 代码修改如下:

/**
* 赢得吃鸡的策略接口,上下文作为参数传入
*/
public interface WinStrategy {
void win(Context context);
} /**
* 采用LYB的模式, 打印出天气情况
*/
public class AlwaysHideWinStrategy implements WinStrategy {
public void win(Context context) {
System.out.println("总是很苟,活得长久; 天气: "+context.getWeather());
}
} /**
* 上下文
*/
@Data
public class Context { private String weather;
WinStrategy winStrategy; public Context(String weather, WinStrategy winStrategy) {
this.weather = weather;
this.winStrategy = winStrategy;
} public void winGame() {
winStrategy.win(this);
System.out.println("天气情况:"+this.weather+"; 采用的策略"+winStrategy.getClass());
} }

上面通过将上下文引用作为参数传递给策略来实现了策略与上下文的通信, 对于不同策略的实现,未必都会用到上下文中的全部信息, 这种情况下传递上下文引用成为了一种"浪费". 因此有的人更愿意将使用的信息作为属性定义在策略实现类中,实现更有针对性的代码

两种方式各有利弊, 传递上下文引用的方式利于扩展, 且可以做到风格统一, 但可能会导致"浪费", 如果扩展太多上下文子类不利于理解. 注入的方式实现在策略类中方式比较简单, 容易实现, 但也会导致策略与其他策略风格不一致.

/**
* 赢得吃鸡的策略接口
*/
public interface WinStrategy {
void win();
} /** * 采用人挡杀人的模式
*/
@AllArgsConstructor
public class AlwaysKillWinStrategy implements WinStrategy { private String weather; public void win() {
System.out.println("总是很钢,大杀四方"+" 天气:"+weather);
}
} public class StrategyTest {
public static void main(String[] args) {
WinStrategy iWillWin = new AlwaysKillWinStrategy("雾天");
Context context = new Context("雾天",iWillWin);
context.winGame();
}
}

总结

优点: 1. 易于扩展;2.避免了if...else... 3. 代码重用

缺点: 调用方需要知道使用的哪种算法, 算法需要完全暴露; 可能会导致实现类过多;

设计模式七: 策略(Strategy)的更多相关文章

  1. C++设计模式实现--策略(Strategy)模式

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/L_Andy/article/details/30489331 一. 举例说明 曾经做了一个程序,程序 ...

  2. Java设计模式之 — 策略(Strategy)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8986285 今天你的leader兴致冲冲地找到你,希望你可以帮他一个小忙,他现在急 ...

  3. Head First 设计模式 - 01. 策略 (Strategy) 模式

    当涉及到"维护"时,为了"复用"目的而使用继承,结局并不完美 P4 对父类代码进行修改时,影响层面可能会很大 思考题 利用继承来提供 Duck 的行为,这会导致 ...

  4. 设计模式 策略-Strategy,装饰-Decorator,观察者-Observer

    重温了Head First 3个设计模式.提炼一下思想,笔记如下. 策略-Strategy 当一个类或类族中重复实现某些同类的方法(behavior)时,考虑使用策略模式. 该模式是将Behavior ...

  5. 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)

    原文:乐在其中设计模式(C#) - 策略模式(Strategy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 策略模式(Strategy Pattern) 作者:webabc ...

  6. 设计模式C++实现(1)——策略(Strategy)模式

    目录 策略模式 应用案例 实现的关键 Talk is cheap,let's See The Code 设计思想 参考 策略模式 策略模式定义了一系列算法和行为(也就是策略),他们可以在运行时相互替换 ...

  7. Strategy Pattern ava设计模式之策略模式

    简介 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式.简单理解就是一组算法,可以互换,再简单点策略就是封装算法. 意图 定义一 ...

  8. JAVA设计模式之策略模式 - Strategy

    在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式. 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 ...

  9. 设计模式之策略模式和状态模式(strategy pattern & state pattern)

    本文来讲解一下两个结构比较相似的行为设计模式:策略模式和状态模式.两者单独的理解和学习都是比较直观简单的,但是实际使用的时候却并不好实践,算是易学难用的设计模式吧.这也是把两者放在一起介绍的原因,经过 ...

随机推荐

  1. SaaS服务和个性化需求,就不能鱼和熊掌兼得吗?

    随时随地.轻松高效,移动工作让人类的自由度最大化.但企业的移动化过程却不轻松:要综合考虑销售.产品.客服.市场销售.人力资源等错综复杂的流程和需求,以及原有IT系统.数据信息的对接. 千企千面,很难有 ...

  2. 理解OSI参考模型(转)

    文章转自 https://www.cnblogs.com/evablogs/p/6709707.html 一个视频网站上不小心搜到网络知识的视频,突然以前大学的没有真正接受的知识点,一下子豁然开朗,赶 ...

  3. Redtiger SQL注入练习(二)

    第六关: 点击 click me,构造url:user=1',返回user not found.user=1'',同样. 猜测是数字型注入,构造order by , user=1 order by  ...

  4. Java的get、post请求

    URLConnection package com.shuzf.http; import java.io.BufferedReader; import java.io.IOException; imp ...

  5. 从HTTL模板引擎看软件设计原则

    HTTL (Hyper-Text Template Language) 是一个高性能的开源JAVA模板引擎, 适用于动态HTML页面输出, 可替代JSP页面, 指令和Velocity相似.作者是阿里巴 ...

  6. Linux(Ubuntu)使用日记------tenserflow安装(pip安装法)

    其实步骤是很简单的,只是一开始在网上找了一份错误的教程的原因,掉入了坑. 安装过程: 1. 检查pip版本 pip3 -V 要求使用最新版的pip 9.0.1,如果不是,按照下面的方法安装最新的pip ...

  7. 离线安装IE 11

    转自:http://blog.sina.com.cn/s/blog_711ab1b10102wzq1.html 1.在D盘下,新建文件夹,取名为“ie”. 2.将官网下载的IE11离线包放到此文件夹中 ...

  8. DRF初识与序列化

    一.Django的序列化方法 1.为什么要用序列化组件 做前后端分离的项目,我们前后端数据交互一般都选择JSON,JSON是一个轻量级的数据交互格式.那么我们给前端数据的时候都要转成json格式,那就 ...

  9. [Codeforces702F]T-Shirts——非旋转treap+贪心

    题目链接: Codeforces702F 题目大意:有$n$种T恤,每种有一个价格$c_{i}$和品质$q_{i}$且每种数量无限.现在有$m$个人,第$i$个人有$v_{i}$元,每人每次会买他能买 ...

  10. ☆ [POI2007] ZAP-Queries 「莫比乌斯反演」

    题目类型:莫比乌斯反演 传送门:>Here< 题意:求有多少对正整数对\((a,b)\),满足\(0<a<A\),\(0<b<B\),\(gcd(a,b)=d\) ...