问题:通过策略模式+工厂模式+模板方法模式实现ifelse优化

项目场景:

提示:这里简述项目相关背景:

示例:商城系统有会员系统,不同会员有不同优惠程度,普通会员不优惠;黄金会员打8折;白金会员优惠50元,再打7折;


问题描述

提示:这里描述项目中遇到的问题:

例如:不同会员处理过程中,业务场景复杂,每种会员的业务逻辑很长,不方便维护。

java 复制代码
public static double quote(String type) {
        double score = 1000;
        double res = 0;
        if (type.equals("1")) {
            res = score;
        } else if (type.equals("2")) {
            res = score - 50;
        } else if (type.equals("3")) {
            res = score * 0.8;
        } else if (type.equals("4")) {
            res = (score - 50) * 0.7;
        }
        return res;
 }

原因分析:

提示:这里填写问题的分析:

业务复杂


解决方案:

提示:这里填写该问题的具体解决方案:

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.third;

import java.math.BigDecimal;


public interface PayStrategy {
    /**
     * 计算费用
     *
     * @param price
     * @date 2025-02-10
     */
    BigDecimal quote(BigDecimal price);
}

具体策略1:非会员,没有优惠

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.third;

import java.math.BigDecimal;

public class OrdinaryStrategy implements PayStrategy{
    @Override
    public BigDecimal quote(BigDecimal price) {
        return price;
    }
}

具体策略2:黄金会员,打八折

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.third;

import java.math.BigDecimal;
import java.util.Objects;

public class GoldStrategy implements PayStrategy{
    @Override
    public BigDecimal quote(BigDecimal price) {

        BigDecimal res = price.multiply(new BigDecimal("0.8"));
        return res;
    }
}

具体策略3:白银会员,先优惠50,后打七折

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.third;

import com.geekmice.springbootmybatiscrud.strategy.first.Strategy;

import java.math.BigDecimal;

public class PlatinumStrategy implements PayStrategy {
    @Override
    public BigDecimal quote(BigDecimal price) {
        BigDecimal res = price.subtract(new BigDecimal("50")).multiply(new BigDecimal("0.7"));
        return res;
    }
}

上下文对象:持有一个Strategy的引用

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.third;

import java.math.BigDecimal;

/**
 * @author Administrator
 */
public class PayContext {

    private PayStrategy payStrategy;

    public void setStrategy(PayStrategy payStrategy) {
        this.payStrategy = payStrategy;
    }

    public BigDecimal getPrice(BigDecimal price) {
        if (payStrategy != null) {
            return payStrategy.quote(price);
        }
        return null;
    }
}

测试使用

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.third;

import java.math.BigDecimal;

public class Demo {
    public static void main(String[] args) {
        PayContext payContext = new PayContext();
        OrdinaryStrategy ordinaryStrategy = new OrdinaryStrategy();
        payContext.setStrategy(ordinaryStrategy);
        System.out.println("普通会员:"+payContext.getPrice(new BigDecimal("100")));

        GoldStrategy goldStrategy = new GoldStrategy();
        payContext.setStrategy(goldStrategy);
        System.out.println("黄金会员:"+payContext.getPrice(new BigDecimal("100")));

        PlatinumStrategy platinumStrategy = new PlatinumStrategy();
        payContext.setStrategy(platinumStrategy);
        System.out.println("白银会员:"+payContext.getPrice(new BigDecimal("100")));
    }
}

结果

普通会员:100

黄金会员:80.0

白银会员:35.0

优化1:新增其他策略,不影响现有的策略

思路:新增策略类,实现策略接口

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.third;

import java.math.BigDecimal;

public class SilverStrategy implements PayStrategy{
    @Override
    public BigDecimal quote(BigDecimal price) {
        return price.subtract(new BigDecimal("50"));
    }
}

package com.geekmice.springbootmybatiscrud.strategy.third;

import java.math.BigDecimal;

public class Demo {
    public static void main(String[] args) {
        PayContext payContext = new PayContext();
        OrdinaryStrategy ordinaryStrategy = new OrdinaryStrategy();
        payContext.setStrategy(ordinaryStrategy);
        System.out.println("普通会员:"+payContext.getPrice(new BigDecimal("100")));

        GoldStrategy goldStrategy = new GoldStrategy();
        payContext.setStrategy(goldStrategy);
        System.out.println("黄金会员:"+payContext.getPrice(new BigDecimal("100")));

        PlatinumStrategy platinumStrategy = new PlatinumStrategy();
        payContext.setStrategy(platinumStrategy);
        System.out.println("白银会员:"+payContext.getPrice(new BigDecimal("100")));

        SilverStrategy silverStrategy = new SilverStrategy();
        payContext.setStrategy(silverStrategy);
        System.out.println("白金会员:"+payContext.getPrice(new BigDecimal("100")));

    }
}

普通会员:100

黄金会员:80.0

白银会员:35.0

白金会员:50

优化2:策略中出现相同逻辑,如何处理

说明:策略2与策略3处理逻辑中都有需要处理的内容,这个内容可能很长,初始化参数,或者校验参数,远程调用获取数据等操作,都是类似的逻辑,可以抽取到抽象类中,子类需要哪个实现哪个方法,重复的直接在父类操作。

策略工厂

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.fifth;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
 * @author mbp
 * @date 2025-02-11
 */
public class StrategyFactory {
    /**
     * 设置策略map
     */
    private static Map<String, Strategy> strategyMap = new HashMap<>(16);

    public static Strategy getStrategyService(String type) {
        return strategyMap.get(type);
    }

    /**
     * 提前策略装入 strategyMap
     */
    public static void register(String type, Strategy strategy) {
        if (Objects.isNull(type)) {
            return;
        }
        strategyMap.put(type, strategy);
    }
}

策略接口

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.fifth;

import org.springframework.beans.factory.InitializingBean;

import java.math.BigDecimal;
/**
 * @author mbp
 * @date 2025-02-11
 */
public interface Strategy extends InitializingBean {
    BigDecimal quote(BigDecimal price);

}

模板方式抽象类

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.fifth;

/**
 * @author mbp
 * @date 2025-02-11
 */
public abstract class BaseMember {
    /**
     * 需要父类执行关键重复逻辑
     */
    protected void exec(){
        System.out.println("处理内容");
    }

}

具体策略1

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.fifth;

import org.springframework.stereotype.Component;

import java.math.BigDecimal;
/**
 * @author mbp
 * @date 2025-02-11
 */
@Component
public class OrdinaryStrategy extends BaseMember  implements Strategy {
    @Override
    public BigDecimal quote(BigDecimal price) {
        this.exec();
        return price;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        StrategyFactory.register("1",this);
    }
}

具体策略2

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.fifth;

import org.springframework.stereotype.Component;

import java.math.BigDecimal;
/**
 * @author mbp
 * @date 2025-02-11
 */
@Component
public class GoldStrategy extends BaseMember implements Strategy {
    @Override
    public BigDecimal quote(BigDecimal price) {
        BigDecimal res = price.multiply(new BigDecimal("0.8"));
        this.exec();
        return res;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        StrategyFactory.register("2", this);
    }

}

具体策略3

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.fifth;

import org.springframework.stereotype.Component;

import java.math.BigDecimal;
/**
 * @author mbp
 * @date 2025-02-11
 */
@Component
public class PlatinumStrategy extends BaseMember implements Strategy {
    @Override
    public BigDecimal quote(BigDecimal price) {
        BigDecimal res = price.subtract(new BigDecimal("50")).multiply(new BigDecimal("0.7"));
        return res;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        StrategyFactory.register("3", this);
    }
}

测试类

java 复制代码
package com.geekmice.springbootmybatiscrud.controller;

import com.geekmice.springbootmybatiscrud.dao.StudentMapper;
import com.geekmice.springbootmybatiscrud.pojo.Student;
import com.geekmice.springbootmybatiscrud.strategy.fifth.Strategy;
import com.geekmice.springbootmybatiscrud.strategy.fifth.StrategyFactory;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Administrator
 */
@RestController
@RequestMapping("/student")
public class StudentController {
    @Resource
    private StudentMapper studentMapper;

    @GetMapping(value = "queryAll")
    public List<Student> queryAll() {
        Strategy strategyService = StrategyFactory.getStrategyService("1");
        System.out.println(strategyService.quote(new BigDecimal("1000")));
        Strategy strategyService2 = StrategyFactory.getStrategyService("2");
        System.out.println(strategyService2.quote(new BigDecimal("1000")));
        Strategy strategyService1 = StrategyFactory.getStrategyService("3");
        System.out.println(strategyService1.quote(new BigDecimal("1000")));
        return new ArrayList<>();

    }

}

优化3:传递策略类型

根据某个策略类型,执行某个策略逻辑

思路:需要保证某个类型对应某个策略类,通过springInitializingBean接口初始化bean,项目启动过程执行实现InitializingBean接口中的afterPropertiesSet方法,在这个方法中初始化map中指定的策略。

策略接口

java 复制代码
public interface Strategy extends InitializingBean {
    BigDecimal quote(BigDecimal price);
}

策略工厂

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.fourth;

import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class StrategyFactory {
    /**
     * 设置策略map
     */
    private static Map<String, Strategy> strategyMap = new HashMap<>(16);

    public static Strategy getStrategyService(String type) {
        return strategyMap.get(type);
    }

    /**
     * 提前策略装入 strategyMap
     */
    public static void register(String type, Strategy strategy) {
        if (Objects.isNull(type)) {
            return;
        }
        strategyMap.put(type, strategy);
    }
}

具体策略1

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.fourth;

import com.geekmice.springbootmybatiscrud.strategy.third.PayStrategy;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
@Component
public class OrdinaryStrategy implements Strategy {
    @Override
    public BigDecimal quote(BigDecimal price) {
//        System.out.println("都要处理的内容");
        return price;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("11111111111");
        StrategyFactory.register("1",this);
    }
}

具体策略2

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.fourth;

import com.geekmice.springbootmybatiscrud.strategy.third.PayStrategy;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
@Component
public class GoldStrategy implements Strategy {
    @Override
    public BigDecimal quote(BigDecimal price) {
        BigDecimal res = price.multiply(new BigDecimal("0.8"));
        return res;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("222222222222");
        StrategyFactory.register("2",this);
    }
}

具体策略3

java 复制代码
package com.geekmice.springbootmybatiscrud.strategy.fourth;

import com.geekmice.springbootmybatiscrud.strategy.third.PayStrategy;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
@Component
public class PlatinumStrategy implements Strategy {
    @Override
    public BigDecimal quote(BigDecimal price) {
        // 都要处理的内容
        // System.out.println("都要处理的内容");
        BigDecimal res = price.subtract(new BigDecimal("50")).multiply(new BigDecimal("0.7"));
        return res;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("3333333333333");
        StrategyFactory.register("3",this);
    }

}

测试

java 复制代码
package com.geekmice.springbootmybatiscrud.controller;

import com.geekmice.springbootmybatiscrud.dao.StudentMapper;
import com.geekmice.springbootmybatiscrud.pojo.Student;
import com.geekmice.springbootmybatiscrud.strategy.first.StrategyFactory;
import com.geekmice.springbootmybatiscrud.strategy.fourth.Strategy;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Administrator
 */
@RestController
@RequestMapping("/student")
public class StudentController {
    @Resource
    private StudentMapper studentMapper;

    @GetMapping(value = "queryAll")
    public List<Student> queryAll() {

        Strategy strategyService =StrategyFactory.getStrategyService("1");
        System.out.println(strategyService);
        System.out.println(strategyService.quote(new BigDecimal("1000")));

        return new ArrayList<>();

    }

}
相关推荐
添砖Java中6 小时前
深度解析策略模式:从理论到企业级实战应用
spring boot·spring·spring cloud·设计模式·maven·策略模式
weixin_4383354011 小时前
设计模式之策略模式
设计模式·策略模式
大雄野比1 天前
Python 实现 macOS 系统代理的设置
python·macos·策略模式
_DCG_1 天前
c++设计模式之策略模式
c++·设计模式·策略模式
FLZJ_KL2 天前
【设计模式】【行为型模式】策略模式(Strategy)
java·设计模式·策略模式·java基础
a.cup3 天前
java---->策略模式
java·开发语言·策略模式
运筹帷幄小红花3 天前
模板方法模式(Template)
模板方法模式
管大虾3 天前
设计模式-策略模式
设计模式·策略模式
Z灏5 天前
Java设计模式---策略模式
java·策略模式