当前位置: 首页 > news >正文

Java设计模式——策略模式

在软件系统可能需要根据不同的情境或条件使用不同的算法或行为,但是这些算法的选择和使用可能会频繁变化。在一个类中或许可以通过一系列的条件判断去区分算法的使用,但是这就会导致代码的臃肿不堪,难以维护和扩展。这时我们需要一种方式来灵活地选择和切换不同的算法。这时就可以考虑策略模式,它的主要优点是实现了算法的解耦,使得算法可以独立于客户端而变化。它提高了代码的可维护性和扩展性,因为新的策略可以很容易地添加到系统中。然而策略模式也可能导致类的数量增加,因为每个算法都需要一个对应的策略类。所以要根据类的数量与灵活性来选择是否使用策略模式。

一、接口方式实现

假定一个促销活动方案例子

/*** 抽象促销策略*/
public interface IPromotionStrategy {void doPromotion();
}/*** 团购优惠策略*/
public class GroupBuyStrategy implements IPromotionStrategy {@Overridepublic void doPromotion() {System.out.println("团购优惠");}
}/*** 返现促销策略*/
public class CashbackStrategy implements IPromotionStrategy {@Overridepublic void doPromotion() {System.out.println("返现促销");}
}/*** 优惠卷抵扣策略*/
public class CouponsStrategy implements IPromotionStrategy {@Overridepublic void doPromotion() {System.out.println("优惠卷抵扣");}
}/*** 无优惠策略*/
public class EmptyStrategy implements IPromotionStrategy {@Overridepublic void doPromotion() {System.out.println("无优惠");}
}/*** 促销活动方案*/
public class PromotionActivity {private IPromotionStrategy promotionStrategy;public PromotionActivity(IPromotionStrategy promotionStrategy) {this.promotionStrategy = promotionStrategy;}public void execute() {promotionStrategy.doPromotion();}
}

 可结合工厂模式来管理策略

/*** 促销策略工厂*/
public class PromotionStrategyFactory {private static final Map<String, IPromotionStrategy> strategyMap = new HashMap<>();private static final IPromotionStrategy EMPTY = new EmptyStrategy();private PromotionStrategyFactory() {}static {strategyMap.put("COUPONS", new CouponsStrategy());strategyMap.put("CASHBACK", new CashbackStrategy());strategyMap.put("GROUPBUY", new GroupBuyStrategy());}public static IPromotionStrategy getPromotionStrategy(String key) {return strategyMap.get(key) == null ? EMPTY : strategyMap.get(key);}public static Set<String> getPromotionStrategyKeys() {return strategyMap.keySet();}}

 编写测试用例

    /*** 策略模式-促销活动方案测试*/@Testpublic void testPromotionActivity() {PromotionActivity activity = new PromotionActivity(new CouponsStrategy());PromotionActivity activity1 = new PromotionActivity(new CashbackStrategy());activity.execute();activity1.execute();}/*** 策略模式-促销活动方案(增强版)测试*/@Testpublic void testPromotionActivityUp() {Set<String> strategyKeys = PromotionStrategyFactory.getPromotionStrategyKeys();IPromotionStrategy strategy = PromotionStrategyFactory.getPromotionStrategy("COUPONS");strategy.doPromotion();}

二、抽象类方式实现

假定一个支付方式选择例子

/*** 抽象支付类*/
public abstract class Payment {public abstract String getName();public ResultMsg pay(String uid, double amount) {if (queryBalance(uid) < amount) {return new ResultMsg(500, "支付失败", "余额不足");}return new ResultMsg(200, "支付成功", "支付金额:" + amount);}protected abstract double queryBalance(String uid);
}/*** 订单类*/
@AllArgsConstructor
public class Order {private String uid;private String orderId;private double amount;public ResultMsg pay() {return pay(PayStrategy.DEFAULT_PAY);}public ResultMsg pay(String key) {Payment payment = PayStrategy.get(key);System.out.println("欢迎使用" + payment.getName() + "支付");System.out.println("本次交易金额为" + amount + "元,开始交易扣款");return payment.pay(uid, amount);}
}/*** 支付宝*/
public class AliPay extends Payment {@Overridepublic String getName() {return "支付宝";}@Overrideprotected double queryBalance(String uid) {return 500;}
}/*** 银联支付*/
public class UnionPay extends Payment {@Overridepublic String getName() {return "银联";}@Overrideprotected double queryBalance(String uid) {return 300;}
}/*** 微信支付*/
public class WechatPay extends Payment {@Overridepublic String getName() {return "微信支付";}@Overrideprotected double queryBalance(String uid) {return 250;}
}/*** 支付策略*/
public class PayStrategy {public static final String ALI_PAY = "AliPay";public static final String WECHAT_PAY = "WechatPay";public static final String UNION_PAY = "UnionPay";public static final String DEFAULT_PAY = "AliPay";private static final Map<String, Payment> paymentMap = new HashMap<>();static {paymentMap.put(ALI_PAY, new AliPay());paymentMap.put(WECHAT_PAY, new WechatPay());paymentMap.put(UNION_PAY, new UnionPay());paymentMap.put(DEFAULT_PAY, new AliPay());}public static Payment get(String key) {if (!paymentMap.containsKey(key)) {return paymentMap.get(DEFAULT_PAY);}return paymentMap.get(key);}
}

编写测试用例

    /*** 策略模式-支付选择*/@Testpublic void testPayChoose() {Order order = new Order("123", "20220719PAY01", 1000);ResultMsg pay = order.pay(PayStrategy.ALI_PAY);System.out.println(pay);}

相关文章:

  • 禁止电子邮箱地址登录WordPress后台的插件No Login by Email Address
  • 郑州大学2024年寒假训练 Day6:动态规划
  • JS前端高频面试
  • 【Vuforia+Unity】AR03-圆柱体物体识别
  • Unity Shader ASE基础效果思路与代码(一):遮罩、硬边溶解、光边溶解、UV扰动
  • 中科大计网学习记录笔记(十四):多路复用与解复用 | 无连接传输:UDP
  • 蓝桥杯-整数删除
  • QT应用软件【协议篇】周立功CAN接口卡代码示例
  • java的反射reflect
  • c语言经典测试题3
  • Shellcode免杀对抗(C/C++)
  • Python接口自动化框架设计到开发,赶紧用起来!
  • Web安全之浅见
  • 2024年2月19日 - mis
  • C#,整数转为短字符串(Short string)的加解密算法与源代码
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • 〔开发系列〕一次关于小程序开发的深度总结
  • C++入门教程(10):for 语句
  • idea + plantuml 画流程图
  • Javascript编码规范
  • java正则表式的使用
  • leetcode388. Longest Absolute File Path
  • Meteor的表单提交:Form
  • Node + FFmpeg 实现Canvas动画导出视频
  • nodejs:开发并发布一个nodejs包
  • PHP 7 修改了什么呢 -- 2
  • Redis 懒删除(lazy free)简史
  • TypeScript实现数据结构(一)栈,队列,链表
  • 阿里云应用高可用服务公测发布
  • 搭建gitbook 和 访问权限认证
  • 二维平面内的碰撞检测【一】
  • 前言-如何学习区块链
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • 云大使推广中的常见热门问题
  • ionic异常记录
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • #NOIP 2014# day.2 T2 寻找道路
  • #vue3 实现前端下载excel文件模板功能
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (poj1.2.1)1970(筛选法模拟)
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转载)(官方)UE4--图像编程----着色器开发
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .NET MVC、 WebAPI、 WebService【ws】、NVVM、WCF、Remoting
  • .net6 webapi log4net完整配置使用流程
  • .Net程序猿乐Android发展---(10)框架布局FrameLayout
  • .net网站发布-允许更新此预编译站点
  • @Mapper作用
  • [@Controller]4 详解@ModelAttribute
  • [BZOJ 3680]吊打XXX(模拟退火)
  • [BZOJ 4598][Sdoi2016]模式字符串