Java设计模式——策略模式

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

一、接口方式实现

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

/**
 * 抽象促销策略
 */
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<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();
    }

}

 编写测试用例

    /**
     * 策略模式-促销活动方案测试
     */
    @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<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 {
    @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<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);
    }
}

编写测试用例

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

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
策略模式(Strategy Pattern)是Java设计模式中的一种行为型模式,它定义了一系列的算法,并将每个算法封装在独立的类中,使得它们可以互相替换。这样可以使得算法的变化独立于使用它们的客户端。 在策略模式中,有三个主要角色: 1. 环境类(Context):持有一个策略类的引用,用于调用具体的策略。 2. 抽象策略类(Strategy):定义了一个公共接口或抽象类,用于具体策略类的统一调用。 3. 具体策略类(Concrete Strategy):实现了抽象策略类定义的接口或抽象类,提供具体的算法实现。 使用策略模式可以实现算法的动态切换,增加新的算法也不会影响到已有的代码。例如,假设我们需要实现一个排序算法,可以定义一个抽象策略类 SortStrategy,然后具体的排序算法(如快速排序、归并排序等)分别实现 SortStrategy,并在环境类中持有 SortStrategy 的引用。这样,通过更换不同的 SortStrategy 对象,就可以在运行时选择不同的排序算法。 策略模式能够有效地解耦策略的定义和使用,提高代码的灵活性和可维护性。同时,它也符合面向对象设计原则中的"开闭原则"(对扩展开放,对修改关闭)和"单一职责原则"(一个类应该只有一个引起变化的原因)。 希望这个简要的介绍能够帮助到你对策略模式的理解。如果还有其他问题,可以继续提问!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值