目录
策略模式【Strategy Pattern】,什么是策略模式?核心思想?角色?优缺点?应用场景?略模式实现案例?
什么是策略模式?
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法或策略,将每个算法封装起来,并且使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户端代码,客户端可以在运行时灵活选择不同的策略。
策略模式核心思想
策略模式的核心思想是将一组可互换的算法封装在独立的类中,使得它们可以在不影响客户端代码的情况下互换使用。通过将算法和业务逻辑分离,策略模式使得客户端代码更具灵活性和可扩展性。
策略模式的角色
(1)策略接口(Strategy)
定义所有具体策略类都需要实现的公共接口。策略接口声明了算法的抽象方法,所有策略都必须实现该方法。
(2)具体策略类(Concrete Strategy)
每个具体策略类实现了策略接口,封装了某个具体的算法或行为。不同的策略类可以提供不同的算法实现。
(3)上下文类(Context)
上下文类维护对某个策略对象的引用,并且调用该策略的方法来执行特定的行为。上下文类通常包含设置策略的方法,允许客户端在运行时更改策略。
策略模式的优缺点
优点
(1)遵循开闭原则
新的策略可以很方便地添加,而不需要修改上下文类的代码,具有良好的扩展性。
(2)消除条件判断
通过使用不同的策略类,避免了在客户端代码中使用大量的 if-else 或 switch 语句,简化了代码结构。
(3)提高代码灵活性和可维护性
算法的实现细节对客户端透明,客户端只需设置合适的策略对象,而不需要关心具体算法的实现。
(4)代码复用性强
策略可以独立于上下文,多个上下文类可以共享相同的策略,从而提高了代码的复用性。
缺点
(1)增加了类的数量
每个策略都是一个独立的类,策略模式可能导致系统中类的数量增加,增加了代码的复杂性。
(2)客户端必须了解不同的策略
客户端需要知道有哪些策略以及如何使用这些策略,这对客户端有一定的要求。
(3)策略间可能产生冗余
不同的策略可能实现的内容相似,导致重复代码,需要通过进一步优化来避免。
策略模式的应用场景
(1)多个算法可以替换使用
当一个系统有多个算法可以互相替代,并且这些算法的选择可能会在运行时发生变化时,策略模式是非常合适的。例如,支付系统可以选择不同的支付方式,排序算法可以根据需求动态切换。
(2)消除冗长的条件判断
如果系统中有大量的 if-else 或 switch-case 语句来决定某种行为时,可以通过策略模式将这些条件判断移除,将每个行为封装为一个策略类。
(3)算法的实现需要与使用分离
当算法的实现和算法的使用场景需要分离时,策略模式可以通过将算法封装在独立的策略类中,从而达到算法与业务逻辑分离的效果。
例如:在图形绘制、文本解析等复杂场景中,不同的绘制或解析方式可以作为不同的策略。
策略模式的典型应用
(1)支付系统
支持不同支付方式(如信用卡、PayPal、银行转账等),每种支付方式可以作为一个独立的策略。
(2)排序算法选择
提供不同的排序算法(如快速排序、冒泡排序、插入排序等),在运行时根据数据特征动态选择最佳算法。
(3)加密解密
在安全通信中,可以使用不同的加密算法(如AES、RSA等),策略模式可以用来在运行时选择合适的加密算法。
(4)日志策略
日志系统可以有不同的输出方式(如控制台输出、文件输出、数据库记录等),可以根据需求在运行时选择合适的输出方式。
策略模式实现案例
刘备要到江东娶老婆了,走之前诸葛亮给赵云(伴郎)三个锦囊妙计,说是按天机拆开解决棘手问题,嘿,还别说,真是解决了大问题,搞到最后是周瑜陪了夫人又折兵呀,那咱们先看看这个场景是什么样子的。
这个场景中的要素:三个妙计,一个锦囊,一个赵云,妙计是小亮同志给的,妙计是放置在锦囊
里,俗称就是锦囊妙计嘛,那赵云就是一个干活的人,从锦囊中取出妙计,执行,然后获胜,用 JAVA 程序怎么表现这个呢?
1、定义一个策略接口
package com.uhhe.common.design.strategy;
/**
* 策略接口
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 9:14
*/
public interface IStrategy {
/**
* 每个锦囊妙计都是一个可执行的算法
*/
void operate();
}
2、具体策略类( 找乔国老帮忙、孙夫人断后、求吴国太开个绿灯)
package com.uhhe.common.design.strategy;
/**
* 找乔国老帮忙,使孙权不能杀刘备
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 9:14
*/
public class BackDoor implements IStrategy {
@Override
public void operate() {
System.out.println("找乔国老帮忙,让吴国太给孙权施加压力");
}
}
package com.uhhe.common.design.strategy;
/**
* 孙夫人断后,挡住追兵
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 9:15
*/
public class BlockEnemy implements IStrategy {
@Override
public void operate() {
System.out.println("孙夫人断后,挡住追兵");
}
}
package com.uhhe.common.design.strategy;
/**
* 求吴国太开个绿灯
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 9:15
*/
public class GivenGreenLight implements IStrategy {
@Override
public void operate() {
System.out.println("求吴国太开个绿灯,放行!");
}
}
3、锦囊,上下文类(Context)
package com.uhhe.common.design.strategy;
/**
* 计谋有了,那还要有锦囊
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 9:17
*/
public class SilkBag {
/**
* 构造函数,使用那个妙计
*/
private final IStrategy strategy;
public SilkBag(IStrategy strategy) {
this.strategy = strategy;
}
/**
* 使用计谋
*/
public void operate() {
this.strategy.operate();
}
}
4、赵云使用锦囊
package com.uhhe.common.design.strategy;
/**
* 策略模式【Strategy Pattern】
* 场景:三个妙计,一个锦囊,一个赵云,妙计是小亮同志给的,妙计是放置在锦囊里,
* 俗称就是锦囊妙计,那赵云就是一个干活的人,从锦囊中取出妙计,执行,然后获胜。
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 9:18
*/
public class ZhaoYun {
/**
* 赵云出场了,他根据诸葛亮给他的交代,依次拆开妙计
* <p>
* 问题:赵云实际不知道是那个策略呀,他只知道拆第一个锦囊,而不知道是BackDoor这个妙计
* 咋办? 似乎这个策略模式已经把计谋名称写出来了
* 错!BackDoor、GivenGreenLight、BlockEnemy只是一个代码,写成first、second、third,没人会说你错!
* <p>
* 策略模式的好处就是:体现了高内聚低耦合的特性
* <p>
* 策略模式:
* ①高内聚低耦合的特点也表现出来了,
* ②扩展性,也就是 OCP 原则,策略类可以继续增加下去,只要修改 SilkBag.java 就可以
*/
public static void main(String[] args) {
SilkBag silkBag;
System.out.println("-----------刚刚到吴国的时候拆第一个-------------");
// 拿到妙计
silkBag = new SilkBag(new BackDoor());
// 拆开执行
silkBag.operate();
System.out.println("\n");
// 刘备乐不思蜀了,拆第二个了
System.out.println("-----------刘备乐不思蜀了,拆第二个了-------------");
silkBag = new SilkBag(new GivenGreenLight());
// 执行了第二个锦囊
silkBag.operate();
System.out.println("\n");
// 被孙权的小兵追了,咋办?拆第三个了
System.out.println("-----------孙权的小兵追了,咋办?拆第三个----------");
silkBag = new SilkBag(new BlockEnemy());
// 孙夫人退兵
silkBag.operate();
System.out.println("\n");
}
}
总结:
策略模式通过将不同的算法封装在独立的类中,使得算法可以互换使用,从而提高系统的灵活性和扩展性。策略模式非常适合那些需要动态选择算法或行为的场景,特别是在消除条件判断和提高代码复用性方面,策略模式是一个非常有效的设计模式。