public class SelfInjuryStrategy implements FightStrategy {
@Override
public void fightEnemy() {
System.out.println(“使用’苦肉计‘取得胜利”);
}
}
/**
- 三十六计之借刀杀人
*/
public class CollateralStrategy implements FightStrategy{
@Override
public void fightEnemy() {
System.out.println(“使用’借刀杀人‘取得胜利”);
}
}
环境角色
环境角色主要是持有一个具体的策略,我们使用构造器在初始化环境类时传入具体的策略
/**
- 环境角色-持有具体策略的引用
*/
public class StrategyContext {
private FightStrategy strategy;
public StrategyContext(FightStrategy strategy) {
this.strategy = strategy;
}
public void fight(){
this.strategy.fightEnemy();
}
}
客户端
/**
- 客户端需要根据具体的对手选择具体的策略
*/
public class FightClient {
public static void main(String[] args) {
FightClient client = new FightClient();
client.fightEnemy(“李四”);
}
private void fightEnemy(String enemyName) {
StrategyContext context = null;
switch (enemyName){
case “张三” :
context = new StrategyContext(new HoneyTrapStrategy());
break;
case “李四”:
context = new StrategyContext(new SelfInjuryStrategy());
break;
case “王二”:
context = new StrategyContext(new CollateralStrategy());
break;
}
context.fight();
}
}
执行结果
扩展
–
在上面例子中客户端需要承担根据敌人选择具体的策略职责,即上面的 case
语句的实现逻辑,把这样一大段代码放在客户端会造成客户端臃肿,影响阅读体验,我们有2种优化策略:
简单工厂
使用简单工厂方法,将选择策略的判断逻辑抽取到工厂类中,客户端传入 enemyName
给简单工厂生成具体策略,实现逻辑如下:
/**
-
简单工厂方法
-
根据敌人名称选择具体的策略
*/
public class StrategyFactory {
public static FightStrategy createFightStrategy(String enemyName){
FightStrategy strategy;
switch (enemyName){
case “张三” :
strategy = new HoneyTrapStrategy();
break;
case “李四”:
strategy = new SelfInjuryStrategy();
break;
case “王二”:
strategy = new CollateralStrategy();
break;
default:
throw new IllegalStateException("Unexpected value: " + enemyName);
}
return strategy;
}
}
接下来改造客户端,选择具体策略的方法使用简单工厂生成:
/**
- 使用简单工厂构建具体的策略
*/
public class FightClient {
public static void main(String[] args) {
FightClient client = new FightClient();
client.fightEnemy(“张三”);
}
private void fightEnemy(String enemyName) {
FightStrategy strategy = StrategyFactory.createFightStrategy(enemyName);
StrategyContext context = new StrategyContext(strategy);
context.fight();
}
}
策略与简单工厂结合
这里主要改造环境角色类,构造方法不再接收具体的策略对象,而是使用 enemyName
作为参数接收,让其拥有根据 enemyName
选择策略的能力,改造后的环境类如下:
/**
- 环境角色 结合简单工厂选择具体的策略
*/
public class StrategyContext {
private FightStrategy strategy;
public StrategyContext(String enemyName) {
switch (enemyName){
case “张三” :
strategy = new HoneyTrapStrategy();
break;
case “李四”:
strategy = new SelfInjuryStrategy();
break;
case “王二”:
strategy = new CollateralStrategy();
break;
default:
throw new IllegalStateException("Unexpected value: " + enemyName);
}
}
public void fight(){
this.strategy.fightEnemy();
}
}
改造后的客户端代码如下:
/**
- 环境角色拥有选择策略的能力,客户端只需要认识Context角色
*/
public class FightClient {
public static void main(String[] args) {
FightClient client = new FightClient();
client.fightEnemy(“王二”);
}
private void fightEnemy(String enemyName) {
StrategyContext context = new StrategyContext(enemyName);
context.fight();
}
}
对比
使用简单工厂方法时客户端需要认识两个类: FightStrategy
, StrategyContext
,而使用策略与简单工厂结合的方式客户端只需要认识 StrategyContext
即可,这使得算法类彻底与客户端分离,耦合度会更低。
应用场景
策略模式的使用场景很多,主要有以下几类:
-
一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。
-
《重构》一书中指出策略模式可以作为优化条件语句的技巧,一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句。
-
系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。
-
系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的数据结构。
-
多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为。
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
中…(img-KzvDQa5v-1714757252691)]
[外链图片转存中…(img-KjDrzHNZ-1714757252692)]
[外链图片转存中…(img-AdpjWBg5-1714757252692)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!