JAVA【设计模式】策略模式

一、定义

在这里插入图片描述

策略模式:指定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

二、示例:

模拟场景:
1、在本案例中我们模拟在购买商品时候使⽤的各种类型优惠券(满减、直减、折扣、n元购),这个场景⼏乎也是⼤家的⼀个⽇常购物省钱渠道,购买商品的时候都希望找⼀些优惠券,让购买的商品更加实惠。

传统编码

通过if判断,券的类型越多,if也就越多,代码冗余,臃肿

package com.qf.design.behavior.strategy.tradition;

public class CouponDiscountService {

    public double discountAmount(int type, double typeContent, double skuPrice, double typeExt){
        //1.直减券
        if (type==1){
            return skuPrice-typeContent;
        }

        //2.满减券
        if (type==2){
            if (skuPrice<typeExt) return skuPrice;
            else return skuPrice-typeContent;
        }

        //3.折扣券
        if (type==3){
            return skuPrice*typeContent;
        }

        //4.n元购
        if (type==4){
            return typeContent;
        }

        return 0D;
    }
}

package com.qf.design.behavior.strategy.tradition;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ApiTest {

    private static  Logger logger= LoggerFactory.getLogger(ApiTest.class);
    public static void main(String[] args) {
        CouponDiscountService couponDiscountService=new CouponDiscountService();
        //1.直减券
        double desc = couponDiscountService.discountAmount(1, 23.5, 55.5, 0);
        logger.info("直减券:{}",desc);
        //3.折扣券
        double discount = couponDiscountService.discountAmount(3, 0.5, 800, 0);
        logger.info("折扣券:{}",discount);
    }
}

策略模式设计

折扣接口

package com.qf.design.behavior.strategy.design;

import java.math.BigDecimal;

public interface ICouponDiscount<T> {

    /**
     * 优惠券⾦额计算
     * @param couponInfo 券折扣信息;直减、满减、折扣、N元购
     * @param skuPrice sku⾦额
     * @return 优惠后⾦额
     */
    BigDecimal discountAmount(T couponInfo,BigDecimal skuPrice);
}

满减

package com.qf.design.behavior.strategy.design.impl;

import com.qf.design.behavior.strategy.design.ICouponDiscount;

import java.math.BigDecimal;
import java.util.Map;

/**
 * 满减
 */
public class MJCouponDiscount implements ICouponDiscount<Map<String,String>> {
    @Override
    public BigDecimal discountAmount(Map<String, String> couponInfo, BigDecimal skuPrice) {
        String x = couponInfo.get("x");
        String o = couponInfo.get("n");
        // ⼩于商品⾦额条件的,直接返回商品原价
        if (skuPrice.compareTo(new BigDecimal(x)) < 0) return skuPrice;
        // 减去优惠⾦额判断
        BigDecimal discountAmount = skuPrice.subtract(new BigDecimal(0));
        if (discountAmount.compareTo(BigDecimal.ZERO) < 1) return
                BigDecimal.ONE;
        return discountAmount;
    }
}

N元购

package com.qf.design.behavior.strategy.design.impl;

import com.qf.design.behavior.strategy.design.ICouponDiscount;

import java.math.BigDecimal;

public class NYGCouponDiscount implements ICouponDiscount<Double> {
    @Override
    public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) {
        return new BigDecimal(couponInfo);
    }
}

直减价

package com.qf.design.behavior.strategy.design.impl;

import com.qf.design.behavior.strategy.design.ICouponDiscount;

import java.math.BigDecimal;

public class ZJCouponDiscount implements ICouponDiscount<Double> {
    @Override
    public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) {
        BigDecimal discountAmount = skuPrice.subtract(new
                BigDecimal(couponInfo));
        if (discountAmount.compareTo(BigDecimal.ZERO) < 1) return
                BigDecimal.ONE;
        return discountAmount;
    }
}

折扣价

package com.qf.design.behavior.strategy.design.impl;

import com.qf.design.behavior.strategy.design.ICouponDiscount;

import java.math.BigDecimal;

public class ZKCouponDiscount implements ICouponDiscount<Double> {
    @Override
    public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) {

        BigDecimal discountAmount = skuPrice.multiply(new
                BigDecimal(couponInfo)).setScale(2, BigDecimal.ROUND_HALF_UP);
        if (discountAmount.compareTo(BigDecimal.ZERO) < 1) return
                BigDecimal.ONE;
        return discountAmount;
    }
}

策略控制类

package com.qf.design.behavior.strategy.design;

import java.math.BigDecimal;

public class Context<T> {
    private ICouponDiscount<T> iCouponDiscount;

    public Context(ICouponDiscount<T> iCouponDiscoun){
        this.iCouponDiscount=iCouponDiscoun;
    }

    public BigDecimal discountAmount(T couponInfo,BigDecimal skuPrice){
        return iCouponDiscount.discountAmount(couponInfo,skuPrice);
    }
}

测试:ApiTest

package com.qf.design.behavior.strategy.design;

import com.qf.design.behavior.strategy.design.impl.MJCouponDiscount;
import com.qf.design.behavior.strategy.design.impl.NYGCouponDiscount;
import com.qf.design.behavior.strategy.design.impl.ZJCouponDiscount;
import com.qf.design.behavior.strategy.design.impl.ZKCouponDiscount;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

public class ApiTest {
    private Logger logger= LoggerFactory.getLogger(ApiTest.class);

    @Test
    public void test_zj(){
        Context<Double> doubleContext = new Context<>(new ZJCouponDiscount());
        BigDecimal bigDecimal = doubleContext.discountAmount(12.3, new BigDecimal(56.3));
        logger.info("直减后的价格:{}",bigDecimal);
    }

    @Test
    public void test_zk(){
        Context<Double> doubleContext = new Context<>(new ZKCouponDiscount());
        BigDecimal bigDecimal = doubleContext.discountAmount(0.5, new BigDecimal(56.3));
        logger.info("折扣后的价格:{}",bigDecimal);
    }

    @Test
    public void test_mj(){
        Context<Map<String, String>> doubleContext = new Context<Map<String, String>>(new MJCouponDiscount());
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("x","100");
        hashMap.put("0","10");
        BigDecimal bigDecimal = doubleContext.discountAmount(hashMap, new BigDecimal(100));
        logger.info("满减后的价格:{}",bigDecimal);
    }

    @Test
    public void test_nyg(){
        Context<Double> doubleContext = new Context<>(new NYGCouponDiscount());
        BigDecimal bigDecimal = doubleContext.discountAmount(60.3, new BigDecimal(56.3));
        logger.info("一元购后的价格:{}",bigDecimal);
    }
}


UML关系图

在这里插入图片描述
总结:
以上的策略模式案例相对来说不并不复杂,主要的逻辑都是体现在关于不同种类优惠券的计算折扣策略上。结构相对来说也⽐较简单,在实际的开发中这样的设计模式也是⾮常常⽤的。另外这样的设计与命令模式、适配器模式结构相似,但是思路是有差异的。

通过策略设计模式的使⽤可以把我们⽅法中的if语句优化掉,⼤量的if语句使⽤会让代码难以扩展,也不好维护,同时在后期遇到各种问题也很难维护。在使⽤这样的设计模式后可以很好的满⾜隔离性与和扩展性,对于不断新增的需求也⾮常⽅便承接。

posted @ 2022-08-30 22:40  雾托邦  阅读(50)  评论(0编辑  收藏  举报