項目場景:
提示:這里簡述項目相關背景:
示例:商城系統有會員系統,不同會員有不同優惠程度,普通會員不優惠;黃金會員打8折;白金會員優惠50元,再打7折;
問題描述
提示:這里描述項目中遇到的問題:
例如:不同會員處理過程中,業務場景復雜,每種會員的業務邏輯很長,不方便維護。
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;}
原因分析:
提示:這里填寫問題的分析:
業務復雜
解決方案:
提示:這里填寫該問題的具體解決方案:
package com.geekmice.springbootmybatiscrud.strategy.third;import java.math.BigDecimal;public interface PayStrategy {/*** 計算費用** @param price* @date 2025-02-10*/BigDecimal quote(BigDecimal price);
}
具體策略1:非會員,沒有優惠
package com.geekmice.springbootmybatiscrud.strategy.third;import java.math.BigDecimal;public class OrdinaryStrategy implements PayStrategy{@Overridepublic BigDecimal quote(BigDecimal price) {return price;}
}
具體策略2:黃金會員,打八折
package com.geekmice.springbootmybatiscrud.strategy.third;import java.math.BigDecimal;
import java.util.Objects;public class GoldStrategy implements PayStrategy{@Overridepublic BigDecimal quote(BigDecimal price) {BigDecimal res = price.multiply(new BigDecimal("0.8"));return res;}
}
具體策略3:白銀會員,先優惠50,后打七折
package com.geekmice.springbootmybatiscrud.strategy.third;import com.geekmice.springbootmybatiscrud.strategy.first.Strategy;import java.math.BigDecimal;public class PlatinumStrategy implements PayStrategy {@Overridepublic BigDecimal quote(BigDecimal price) {BigDecimal res = price.subtract(new BigDecimal("50")).multiply(new BigDecimal("0.7"));return res;}
}
上下文對象:持有一個Strategy的引用
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;}
}
測試使用
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:新增其他策略,不影響現有的策略
思路:新增策略類,實現策略接口
package com.geekmice.springbootmybatiscrud.strategy.third;import java.math.BigDecimal;public class SilverStrategy implements PayStrategy{@Overridepublic 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處理邏輯中都有需要處理的內容,這個內容可能很長,初始化參數,或者校驗參數,遠程調用獲取數據等操作,都是類似的邏輯,可以抽取到抽象類中,子類需要哪個實現哪個方法,重復的直接在父類操作。
策略工廠
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);}
}
策略接口
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);}
模板方式抽象類
package com.geekmice.springbootmybatiscrud.strategy.fifth;/*** @author mbp* @date 2025-02-11*/
public abstract class BaseMember {/*** 需要父類執行關鍵重復邏輯*/protected void exec(){System.out.println("處理內容");}}
具體策略1
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 {@Overridepublic BigDecimal quote(BigDecimal price) {this.exec();return price;}@Overridepublic void afterPropertiesSet() throws Exception {StrategyFactory.register("1",this);}
}
具體策略2
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 {@Overridepublic BigDecimal quote(BigDecimal price) {BigDecimal res = price.multiply(new BigDecimal("0.8"));this.exec();return res;}@Overridepublic void afterPropertiesSet() throws Exception {StrategyFactory.register("2", this);}}
具體策略3
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 {@Overridepublic BigDecimal quote(BigDecimal price) {BigDecimal res = price.subtract(new BigDecimal("50")).multiply(new BigDecimal("0.7"));return res;}@Overridepublic void afterPropertiesSet() throws Exception {StrategyFactory.register("3", this);}
}
測試類
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 {@Resourceprivate 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:傳遞策略類型
根據某個策略類型,執行某個策略邏輯
思路:需要保證某個類型對應某個策略類,通過spring
中InitializingBean
接口初始化bean
,項目啟動過程執行實現InitializingBean
接口中的afterPropertiesSet
方法,在這個方法中初始化map中指定的策略。
策略接口
public interface Strategy extends InitializingBean {BigDecimal quote(BigDecimal price);
}
策略工廠
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
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 {@Overridepublic BigDecimal quote(BigDecimal price) {
// System.out.println("都要處理的內容");return price;}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("11111111111");StrategyFactory.register("1",this);}
}
具體策略2
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 {@Overridepublic BigDecimal quote(BigDecimal price) {BigDecimal res = price.multiply(new BigDecimal("0.8"));return res;}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("222222222222");StrategyFactory.register("2",this);}
}
具體策略3
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 {@Overridepublic BigDecimal quote(BigDecimal price) {// 都要處理的內容// System.out.println("都要處理的內容");BigDecimal res = price.subtract(new BigDecimal("50")).multiply(new BigDecimal("0.7"));return res;}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("3333333333333");StrategyFactory.register("3",this);}}
測試
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 {@Resourceprivate 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<>();}}