一、什么是策略模式
策略模式属于行为型设计模式。定义了一系列算法,并将这些算法封装到一个类中,使得他们可以相互替换。这样,我们可以在改变某个对象使用的算法的情况下,选择一个合适的算法来处理特定的任务,主要解决多重if-else的判断逻辑。
二、角色组成
- 环境类(Context):环境类是策略模式的核心类,它持有一个策略对象的引用,并在需要时调用策略对象的方法。
- 抽象策略类(Strategy):定义了策略方法,这些方法表示不同的策略行为。
- 具体策略类(Concrete Strategy):抽象策略类的实现,它实现了抽象策略类中定义的策略方法,并提供了具体的算法实现。不同的具体策略类具有不同的实现算法,它们之间可以相互替换,使得环境类在运行时可以动态地改变策略。
三、优缺点
优点:
- 算法可以自由切换。
- 避免使用多重条件判断。
- 扩展性良好
缺点:
- 策略类会增多。
- 所有策略类都需要对外暴露。
- 判断逻辑在客户端,需求改变时,要更改客户端的程序。
四、应用场景
4.1 生活场景
- 手机开锁方式:密码、指纹、面部识别
- 出游的交通方式:自驾、汽车、火车、飞机、高铁,每一种方式都是一个策略。
- 开通csdn会员的方式:月卡、年卡、超级年卡、两年卡、连续包月。
4.2 java场景
- Spring Security中的认证和授权策略:在Spring Security中,可以使用不同的策略来定义认证和授权的行为,例如PasswordAuthentication(密码验证)、RememberMeAuthentication(记住我功能验证)、RoleBasedAuthorization(基于角色的授权)等。通过配置不同的策略,可以灵活地适应不同的安全需求。
- Comparator接口:在使用排序算法时,可以通过实现Comparator接口来定义不同的比较策略,从而可以根据需求对对象进行自定义排序。
- 线程池(ThreadPoolExecutor):在ThreadPoolExecutor中,可以通过设定不同的拒绝策略(RejectedExecutionHandler)来处理无法提交的新任务。拒绝策略可以根据系统的需求选择不同的处理方式,如抛出异常、丢弃任务等。
五、代码实现
下面以视频平台为例,解释一下策略模式。
- 环境类(Context):VideoContext
- 抽象策略类(Strategy):VideoStrategy
- 具体策略类(Concrete Strategy):DyVideoStrategy、WxVideoStrategy、KsVideoStrategy
5.0、UML类图
5.1、VideoContext——环境类(Context)
/**
* @author Created by njy on 2023/5/25
* 1.策略环境类(Context)
* 在初始化VideoContext对象时,将所有策略实现类塞进Map中,
* key为视频类型(dy、ks、wx) value为对应的视频实现类
* 通过getVideoStrategy方法,根据videoType从map中渠道对应的视频策略
* 从而隐藏了策略的具体实现逻辑。这种方式可以遵循开闭原则,因为在新增视频类型时,只需要增加对应的实现类
*/
@Component
public class VideoContext {
private static final Map<String, VideoStrategy> videoMap = new HashMap<>();
/**
* 对象初始化时,将所有策略实现类加入到map中
* @param videoStrategies
*/
public VideoContext(List<VideoStrategy> videoStrategies) {
videoStrategies.forEach(strategy -> videoMap.put(strategy.getVideoType(), strategy));
}
/**
* 根据videoType获取对应的策略实现类
* @param videoType
* @return
*/
public VideoStrategy getVideoStrategy(String videoType){
VideoStrategy videoStrategy = videoMap.get(videoType);
if (videoStrategy==null) {
throw new RuntimeException("videoType inValid!");
}
return videoStrategy;
}
}
5.2、VideoStrategy——抽象策略类(Strategy)
/**
* @author Created by njy on 2023/5/25
* 2.抽象策略类(Strategy)
*/
public interface VideoStrategy {
//刷视频
String brushVideo();
//视频类型
String getVideoType();
}
5.3、具体策略类(Concrete Strategy)
/**
* @author Created by njy on 2023/5/25
* 3.具体策略类(Concrete Strategy):微信
*/
@Component
public class WxVideoStrategy implements VideoStrategy{
@Override
public String brushVideo() {
return "我在刷微信视频号";
}
@Override
public String getVideoType() {
return "wx";
}
}
/**
* @author Created by njy on 2023/5/25
* 3.具体策略类(Concrete Strategy):快手
*/
@Component
public class KsVideoStrategy implements VideoStrategy{
@Override
public String brushVideo() {
return "我在刷快手";
}
@Override
public String getVideoType() {
return "ks";
}
}
/**
* @author Created by njy on 2023/5/25
* 3.具体策略类(Concrete Strategy):抖音
*/
@Component
public class DyVideoStrategy implements VideoStrategy{
@Override
public String brushVideo() {
return "我在刷抖音";
}
@Override
public String getVideoType() {
return "dy";
}
}
5.4、TestStrategy
/**
* @author njy
* @date 2023/5/24 13:58
* 策略模式测试类
*/
@SpringBootTest
public class TestStrategy {
@Autowired
private VideoContext videoContext;
@Test
void testStrategy(){
//策略模式
VideoStrategy video1 = videoContext.getVideoStrategy("dy");
String v1 = video1.brushVideo();
System.out.println("v1 : " + v1);
VideoStrategy video2 = videoContext.getVideoStrategy("ks");
String v2 = video2.brushVideo();
System.out.println("v2 : " + v2);
VideoStrategy video3 = videoContext.getVideoStrategy("wx");
String v3 = video3.brushVideo();
System.out.println("v3 : " + v3);
}
}
END:更多设计模式的介绍,推荐移步至👉 23种设计模式学习导航(Java完整版)👈