策略模式是什么?怎么使用?
共 5741字,需浏览 12分钟
·
2021-05-02 09:58
作者:溪~源
blog.csdn.net/xuan_lu/article/details/114417396
定义
首先介绍一下众多博客文章中提到的策略模式的概念,针对于文章结构构成,请允许小编在此处再细说一下。
策略模式:百度百科中引述为:指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。
策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。 策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。
【此处的算法,大家可以理解为解决业务需求的方法。】
对于这些概念大家理解起来或许有些抽象,耐心往下读,相信大家肯定会有所收获。
组成
环境(Context)角色: 持有一个Strategy的引用。 抽象策略(Strategy)角色: 这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。 具体策略(ConcreteStrategy)角色: 包装了相关的算法或行为。
理解
对于设计模式中的策略模式,大家众多的解释可能侧重与解决if…else,switch-cas这种条件语句的优化,小编简单谈一下我在项目中实际应用和理解吧;对于策略模式按照上面给予的定义理解,是将多个业务节点具备的共同算法再次顶层抽象为接口,处理不同业务需求时,则产生的行为不同,即具体行为由其实现类解决;注重词:相同算法,,顶层抽出。
再简单举例说明一下,比如工作的OA系统中,流程节点具体相同的功能:提交,回退,撤回等等(抽象策略类);但是每个流程节点所实现的功能不同(具体策略类);
实现
小编以我们日常生活中最常见的支付方式为例,解答策略模式的应用。
无论使用xiaomi,huawei,apple均存在相同的行为(算法),例如:支付方式不同,客户端享受的优惠力度不等。故我们将支付作为共同的接口抽象出来。
UML
抽象策略类
将支付作为共同算法,顶层抽象。
/**
* @author wx
* @date 2021/03/05 1:50 下午
*/
public interface PayStrategy {
void pay(double money);
}
具体策略类
MiPAY
/**
* @author wx
* @date 2021/03/05 1:51 下午
*/
public class MiPayStrategy implements PayStrategy{
@Override
public void pay(double money) {
double payMoney = money * 0.87;
double discountMoney = money - payMoney;
System.out.println("使用Mi pay成功支付" + payMoney + "元,优惠" + discountMoney + "元");
}
}
HuaWeiPAY
/**
* @author wx
* @date 2021/03/05 1:50 下午
*/
public class HuaWeiPayStrategy implements PayStrategy{
@Override
public void pay(double money) {
double payMoney = money * 0.85;
double discountMoney = money - payMoney;
System.out.println("使用HuaWei pay成功支付" + payMoney + "元,优惠" + discountMoney + "元");
}
}
ApplePAY
/**
* @author wx
* @date 2021/03/05 1:52 下午
*/
public class ApplePayStrategy implements PayStrategy{
@Override
public void pay(double money) {
double payMoney = money * 0.82;
double discountMoney = money - payMoney;
System.out.println("使用Apple pay成功支付" + payMoney + "元,优惠" + discountMoney + "元");
}
}
环境类
供客户端调用,并选择具体策略
/**
* @author wx
* @date 2021/03/05 1:53 下午
*/
public class PayContext {
//依赖策略接口属性
private PayStrategy payStrategy;
public void setPayStrategy(PayStrategy payStrategy) {
this.payStrategy = payStrategy;
}
/**
* 提供外部访问方法
* @param money
*/
public void payMoney(double money) {
payStrategy.pay(money);
}
}
客户端
客户端则已知选择的支付方式,可以服务端依据不同支付策略选择折扣。
/**
* @author wx
* @date 2021/03/05 1:59 下午
*/
public class PayClient {
public static void main(String[] args) {
//创建支付上下文
PayContext payContext = new PayContext();
//创建支付策略,客户端已知存在具体策略
PayStrategy miPayStrategy = new MiPayStrategy();
payContext.setPayStrategy(miPayStrategy);
payContext.payMoney(100);
System.out.println("-------改变支付策略--------");
PayStrategy applePayStrategy = new ApplePayStrategy();
payContext.setPayStrategy(applePayStrategy);
payContext.payMoney(100);
}
}
执行结果:
理解了策略模式的使用,下面简单谈谈该模式的优点和缺点:
优点:
毫不疑问复合设计模式中的开闭原则,新增支付方式则扩展策略类即可,无须改动其他策略类的实现; 消除if-else类似的判断语句,整合代码结构,符合代码整洁之道;
缺点:
从类的数量上而言,若策略选择很多,则造成策略类数量增加; 所有策略类都需要对外暴露。即客户端必须知道所有的策略类,并自行决定使用哪一个策略类,故不得不向客户暴露具体的实现。
类比其他模式
策略模式和状态模式:
一、执行方式:
策略模式:客户端策略条件选择只执行一次; 状态模式:随着实例参数(对象实例的状态)的改变不停地更改执行模式。
简言之,策略模式只是在对象初始化的时候更改执行模式,而状态模式是根据对象实例的周期时间而动态地改变对象实例的执行模式。
二、环境类
策略模式:环境类自己选择一个具体策略类,具体策略类无须关心环境类 ; 状态模式:环境类由于外在因素需要放进一个具体状态中,以便通过其方法实现状态的切换 ,因此环境类和状态类之间存在一种双向的关联关系。
简言之,使用策略模式时客户端需要知道所选的具体策略是哪一个;
而使用状态模式时, 客户端无须关心具体状态 ,环境类的状态会根据用户的操作自动转换。