在软件系统可能需要根据不同的情境或条件使用不同的算法或行为,但是这些算法的选择和使用可能会频繁变化。在一个类中或许可以通过一系列的条件判断去区分算法的使用,但是这就会导致代码的臃肿不堪,难以维护和扩展。这时我们需要一种方式来灵活地选择和切换不同的算法。这时就可以考虑策略模式,它的主要优点是实现了算法的解耦,使得算法可以独立于客户端而变化。它提高了代码的可维护性和扩展性,因为新的策略可以很容易地添加到系统中。然而策略模式也可能导致类的数量增加,因为每个算法都需要一个对应的策略类。所以要根据类的数量与灵活性来选择是否使用策略模式。
一、接口方式实现
假定一个促销活动方案例子
- /**
- * 抽象促销策略
- */
- public interface IPromotionStrategy {
- void doPromotion();
- }
-
-
- /**
- * 团购优惠策略
- */
- public class GroupBuyStrategy implements IPromotionStrategy {
- @Override
- public void doPromotion() {
- System.out.println("团购优惠");
- }
- }
-
-
- /**
- * 返现促销策略
- */
- public class CashbackStrategy implements IPromotionStrategy {
- @Override
- public void doPromotion() {
- System.out.println("返现促销");
- }
- }
-
-
- /**
- * 优惠卷抵扣策略
- */
- public class CouponsStrategy implements IPromotionStrategy {
- @Override
- public void doPromotion() {
- System.out.println("优惠卷抵扣");
- }
- }
-
-
- /**
- * 无优惠策略
- */
- public class EmptyStrategy implements IPromotionStrategy {
- @Override
- public 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
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
getPromotionStrategyKeys() { - return strategyMap.keySet();
- }
-
- }
编写测试用例
- /**
- * 策略模式-促销活动方案测试
- */
- @Test
- public void testPromotionActivity() {
- PromotionActivity activity = new PromotionActivity(new CouponsStrategy());
- PromotionActivity activity1 = new PromotionActivity(new CashbackStrategy());
- activity.execute();
- activity1.execute();
- }
-
- /**
- * 策略模式-促销活动方案(增强版)测试
- */
- @Test
- public void testPromotionActivityUp() {
- Set
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 {
- @Override
- public String getName() {
- return "支付宝";
- }
-
- @Override
- protected double queryBalance(String uid) {
- return 500;
- }
- }
-
-
- /**
- * 银联支付
- */
- public class UnionPay extends Payment {
- @Override
- public String getName() {
- return "银联";
- }
-
- @Override
- protected double queryBalance(String uid) {
- return 300;
- }
- }
-
-
- /**
- * 微信支付
- */
- public class WechatPay extends Payment {
- @Override
- public String getName() {
- return "微信支付";
- }
-
- @Override
- protected 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
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);
- }
- }
编写测试用例
- /**
- * 策略模式-支付选择
- */
- @Test
- public void testPayChoose() {
- Order order = new Order("123", "20220719PAY01", 1000);
- ResultMsg pay = order.pay(PayStrategy.ALI_PAY);
- System.out.println(pay);
- }