假设有一个销售系统,需要根据不同的促销活动对商品进行打折或者其他形式的优惠。这些促销活动可以是针对不同商品类别的,比如男装、女装等。
策略者模式在销售系统、支付系统、游戏开发等领域都有广泛的应用。
/**
* 具体策略活动A
*/
public class StrategyA implements Strategy {
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Override
public void show() {
logger.error("活动A,减999!");
}
}
/**
* 活动B
*/
public class StrategyB implements Strategy {
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Override
public void show() {
logger.error("活动B,减999999!");
}
}
/**
* 定义所有活动的公共接口
*/
public interface Strategy {
void show();
}
/**
* 定义环境角色(Context):用于连接上下文,即把促销活动推销给客户,这里可以理解为销售员
*/
public class ManStrategy {
/**
* 持有策略者角色的应用(传入啥执行啥)
* SalesMan salesMan = new SalesMan(new StrategyA());
* SalesMan salesManB = new SalesMan(new StrategyB());
*/
private Strategy strategy;
/**
* 初始化时 将具体的策略者 赋值给当前策略者引用
* @param strategy
*/
public ManStrategy(Strategy strategy){
this.strategy = strategy;
}
/**
* 展示具体的策略
*/
public void showInfoStrategy(){
strategy.show();
}
}
public class HandlerStrategyFactory {
private static final Map<String, Strategy> map = new HashMap<>();
static {
map.put("男装",new StrategyA());
map.put("女装",new StrategyB());
}
public static Strategy getStrategy(String type){
return map.get(type);
}
}
public class StrategyDemo {
public static void main(String[] args) {
// 对象模式
ManStrategy manStrategy = new ManStrategy(new StrategyB());
manStrategy.showInfoStrategy();
// --------------------------- map集合 --------------------------
// 根据对应各key 找到对应的实现类 然后执行对应方法 MAP集合 方式
Strategy strategy = HandlerStrategyFactory.getStrategy("女装");
strategy.show();
}
}
策略工厂模式是一种行为型设计模式,用于灵活选择不同算法,而不必改变代码结构。
电商系统需要根据不同促销活动对商品进行打折,促销策略基于活动季节、产品类型等选择。
PromotionStrategy
,包含applyDiscount()
方法。SpringFestivalPromotion
、MemberDayPromotion
。PromotionStrategyFactory
,根据需求选择合适的促销策略。策略工厂模式提供了灵活性和可维护性,使系统更加健壮。
/**
* 抽象策略接口
*/
public interface PromotionStrategy<R,T,U> {
/**
* 应用折扣
* @param t 商品信息
* @param u 用户信息
* @return 折扣后的最终价格
*/
R applyDiscount(T t, U u);
}
package com.hrfan.java_se_base.pattern.strategy_pattern;
import com.hrfan.java_se_base.log.model.UserInfoToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* 春节促销 策略实现类
*/
@Service
public class SpringFestivalPromotion implements PromotionStrategy<BigDecimal, String, UserInfoToken> {
private final Logger logger = LoggerFactory.getLogger(SpringFestivalPromotion.class);
/**
* 春节折扣信息
* @param goodsName 商品信息
* @param userInfoToken 用户信息
* @return
*/
@Override
public BigDecimal applyDiscount(String goodsName, UserInfoToken userInfoToken) {
logger.error("============= {},春节大促销,原价100,现在6折 =============",goodsName);
BigDecimal account = new BigDecimal("100");
BigDecimal res = account.multiply(new BigDecimal("0.6")).setScale(2,BigDecimal.ROUND_HALF_UP);
logger.error("============= 最终价格仅为:{},速来抢购! =============",res);
return res;
}
}
package com.hrfan.java_se_base.pattern.strategy_pattern;
import com.hrfan.java_se_base.log.model.UserInfoToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* 会员日策略实现类
*/
@Service
public class MemberDayPromotion implements PromotionStrategy<BigDecimal,String, UserInfoToken> {
private final Logger logger = LoggerFactory.getLogger(MemberDayPromotion.class);
/**
* 会员日商品促销策略
* @param goodsName 商品信息
* @param userInfoToken 用户信息
* @return 最终优惠后的价格
*/
@Override
public BigDecimal applyDiscount(String goodsName, UserInfoToken userInfoToken) {
logger.error("============= {},会员日大促销,原价100,现在3折 =============",goodsName);
BigDecimal account = new BigDecimal("100");
BigDecimal res = account.multiply(new BigDecimal("0.3")).setScale(2,BigDecimal.ROUND_HALF_UP);
logger.error("============= 最终价格仅为:{},速来抢购! =============",res);
return res;
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 策略工厂
*/
@Service
public class PromotionStrategyFactory {
@Resource
private ApplicationContext context;
/**
* 选择对应的策略
*/
public PromotionStrategy createPaymentStrategy(String paymentMethod) {
try {
return context.getBean(paymentMethod, PromotionStrategy.class);
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException("未匹配到对应策略:" + paymentMethod);
}
}
}
import com.hrfan.java_se_base.config.ResultObject;
import com.hrfan.java_se_base.log.model.UserInfoToken;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.math.BigDecimal;
/**
* 策略模式测试方法
*/
@RestController
@RequestMapping("/v1/strategy/")
public class StrategyController {
@Resource
private PromotionStrategyFactory promotionStrategyFactory;
@PostMapping("/getLastPrice")
public ResultObject getLastPrice(@RequestParam("type") String type, UserInfoToken userInfoToken){
ResultObject instance = ResultObject.createInstance(true);
// 获取商品的最终价格 (根据传入的策略然后选择对应的实现类 该type就是对应实现类的名称)
PromotionStrategy strategy = promotionStrategyFactory.createPaymentStrategy(type);
BigDecimal res = (BigDecimal) strategy.applyDiscount("鸡蛋", userInfoToken);
instance.setData(res);
instance.setMessage("获取成功!");
return instance;
}
}