详解Java策略模式
作者:Java架构没有996 发布时间:2022-03-20 12:17:05
一、策略模式到底是什么?
策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
简单的说,策略模式代表了一类算法的通用解决方案,你可以在运行时选择使用哪种解决方案。
策略模式的重心
策略模式的重心不是如何实现算法, 而是如何组织、调用这些算法, 从而使得程序结构更加灵活,具有更好的维护性和扩展性。
算法的平等性
策略模式一个很大的特点就是各个策略算法的平等性。对于一系列具体的策略算法,地位都是一样的,因此可以实现算法之间可以互相替换。所有的策略算法在实现上也是相互独立的,相互之间是没有依赖的。所以可以这样描述这一系列策略算法:策略算法是相同行为的不同实现。
运行时策略的唯一性
运行期间,策略模式在每一个时刻只能使用一个具体的策略实现对象,虽然可以动态地在不同的策略实现中切换,但是同时只能使用一个。
公有的行为
经常见到的是,所有的具体策略都有一些公有的行为。这时候,就应该把这些公有的行为放到共同的抽象策略角色
Strategy类里面。这时不能使用接口,应该使用抽象类来实现。
二、策略模式的结构
策略模式包含三部分内容:(如下图所示)
a.一个或多个使用策略对象的客户.(环境角色)
b.一个代表某个算法的接口, 它是策略模式的接口. (抽象策略角色)
c.一个或多个该接口的具体实现, 它们代表了算法的多种实现.(具体策略角色)
三、策略模式的应用
a.容错恢复机制, 程序运行的时候, 如果发生某种错误, 系统并不会直接挂掉或者说影响系统的其他功能点.
而是系统可以容忍这样的错误, 并且事先提供好了这种容错恢复机制, 来使得程序正常的运行下去.
例如: 一个系统要对所有的操作进行日志记录, 且需要把日志记录落库, 方便后续的使用, 但是在把日志记录落库的时候,
可能会发生错误, 如数据库出现问题, 那就先可以记录在文件里面, 等到数据库问题修复, 再把文件中的日志记录同步到数据库中去
对于这样的功能设计, 可以采用策略设计模式, 根据需要在运行期间进行动态的切换.
b.假设现在要设计一个会员机制的购物系统, 对本系统的所有SVIP提供打八折的购物优惠,
对本系统的所有VIP提供打九折的购物优惠, 对非会员购物不打折. 那么对于这样的系统功能设计, 也可以采用策略模式来设计.
c.使用不同的条件(物品的重量或者颜色等)来筛选库存中的物品, 可以将这一模式应用到更广泛的领域,
比如使用不同的标准来验证输入的有效性, 使用不同的方式来分析或者格式化输入.
四、策略模式Demo
假设现在需要根据业务的需求,对调用接口传进来的参数,选择合适的策略进行处理,这里假设有策略一和策略二。
Client:
/**
* @author lyh
* @version v-1.0.0
* @since 2021/6/2
*/
public class Client {
public static void main(String[] args) {
//根据需要客户自行选择策略
//加入Java开发交流君样:756584822一起吹水聊天
//选择策略1
StrategyObj strategyOne = new StrategyObj(new StrategyOne());
System.out.println(strategyOne.strategy("one"));
//选择策略2
StrategyObj strategyTwo = new StrategyObj(new StrategyTwo());
System.out.println(strategyTwo.strategy("two"));
}
}
输出:
执行策略1!
执行策略2!
Process finished with exit code 0
策略接口:
/**
* @desc:策略接口
*/
public interface Strategy {
String execute(String s);
}
/**
* @desc:策略接口封装
*/
public class StrategyObj {
private final Strategy strategy;
public StrategyObj(Strategy v) {
this.strategy = v;
}
public String strategy(String s) {
return strategy.execute(s);
}//加入Java开发交流君样:756584822一起吹水聊天
}
策略实现:
/**
* @desc:策略一
*/
public class StrategyOne implements Strategy {
@Override
public String execute(String s) {
return "执行策略1!";
}
}
/**
* @desc:策略二
*/
public class StrategyTwo implements Strategy {
@Override
public String execute(String s) {
return "执行策略2!";
}
}
五、使用Lambda表达式
通过上面的demo应该可以意识到Strategy是一个函数式接口;除此之外,它还与Predicate<String>
具有同样的函数描述。这意味着我们不需要声明新的类来实现不同的策略,通过直接传递Lambda表达式就能达到同样的目的且更简洁。
public class Client {
public static void main(String[] args) {
StrategyObj strategyOne = new StrategyObj((String s) -> {return "执行策略1";});
System.out.println(strategyOne.strategy("one"));
//加入Java开发交流君样:756584822一起吹水聊天
StrategyObj strategyTwo = new StrategyObj((String s) -> {return "执行策略2";});
System.out.println(strategyTwo.strategy("two"));
}
}
Lambda表达式避免了采用策略设计模板时僵化的模板代码。仔细看上面的代码会发现,Lambda表达式实际已经对策略进行了封装, 这就是创建策略设计模式的初衷.
六、策略模式的优缺点
优点
a.使用策略模式可以避免使用多重条件if…else if…else语句, 多重条件不易维护且代码可读性差.
b.策略模式提供了管理相关的算法族的办法. 策略类的等级结构定义了一个算法或者行为族. 恰当使用继承可以把公共的代码移到父类里面, 从而避免代码重复
缺点
a.客户端必须知道所有的策略类, 并自行决定使用哪一个策略类. 这就意味着客户端必须理解这些算法的区别, 以便适时选择恰当的算法类. 换言之, 策略模式只适用于客户端知道算法或行为的情况.
b.由于策略模式把每个具体的策略实现都单独封装成类, 如果备选的策略很多的话, 那么对象的数目就会很多.
来源:https://blog.csdn.net/wj1314250/article/details/117923328


猜你喜欢
- 1、什么是委托从数据结构来讲,委托是和类一样是一种用户自定义类型。委托是方法的抽象,它存储的就是一系列具有相同签名和返回回类型的方法的地址。
- 今天给大家讲讲 SpringBoot 框架 整合 Elasticsearch 实现海量级数据搜索。一、简介在上篇ElasticSe
- java实体类转成map1.第一种 <!-- 配置gson -->  
- 本文实例讲述了C#微信公众号与订阅号接口开发示例代码。分享给大家供大家参考,具体如下:using System;using System.W
- 本文实例讲述了Spring使用ClassPathResource加载xml资源。分享给大家供大家参考,具体如下:一 代码package le
- 本文主要介绍了java(包括springboot)读取resources下文件方式实现,分享给大家,具体如下:1、使用项目内路径读取,该路径
- 双向信号和竞赛(Two-Way Signaling and Races) Monitor.Pulse方法的一个重要特性是它是异步执
- 一:item的根布局设置Android:clickable="true",之后导致item点击事件失效,对根
- // 1. 实现一个函数,在一个有序整型数组中二分查找出指定的值,找到则返回该值的位置,找不到返回 -1。package demo;publ
- webp格式图片webp格式图片是google推出的,相比jpg png有着巨大的优势,同样质量的图片webp格式的图片占用空间更小,在像电
- SpringBoot是什么?SpringBoot是spring家族中微型框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。
- 一、项目简述功能包括: 登录注册,办理借阅。借阅记录,预约借阅,借出未还, 借阅逾期,学生管理,图书管理,书库分类查询搜索。二、项目运行环境
- Android日期选择控件效果如下:调用的代码:@OnClick(R.id.btn0) public void btn0() { final
- 大家好哇,又是我,梦辛工作室的灵,今天来给大家讲解下如何实现 安卓的侧边弹窗,先大概讲下基本原理吧,其实很简单,就是一个进出动效,用 位移
- 问题springboot 集成springcloud时常常由于版本问题而报错,如下:com.sun.jersey.api.client.Cl
- 一、关联映射举例关系说明数据库创建表,student,teacher关系说明:一个老师可以有多个学生一个学生只有一个老师一个老师对学生:一对
- 最近碰到这么个恶心的问题问题:有个arr文件被放到Module A中引用,现在Module B又依赖了Module A,则在编译过程中会发生
- 验证码及它的作用验证码为全自动区分计算机和人类的图灵测试的缩写,是一种区分用户是计算机的公共全自动程序,这个问题可以由计算机生成并评判,但是
- 算法思想快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-
- 方法1: int d=10; d.ToString("x") //或把x改为X,,,就变成了16位的字符串了. int