首先声明一下,本文章大致内容是来自:https://blog.youkuaiyun.com/u011659172/article/details/79140561
主要记录一下自己实现的过程,方便以后查看。
一个项目写下来,感觉里面代码很杂,写得不好。所以就去接触了设计模式,本篇文章的策略模式,主要是解决多重if...else。
比如一段代码:
public Object feedback(String type) {
if("a".equals(type)){
System.out.println("这是a");
}
if("b".equals(type)){
System.out.println("这是b");
}
if("c".equals(type)){
System.out.println("这是c");
}
}
这样看着可能还好,但是要是还有defg等等内容的时候,维护起来就很麻烦。所以这个时候就要用到策略模式去解决。
优化之后就成了这样:
public Object feedback(String type)
{
return strategyContext.calculatePrice(type);
}
是不是感觉干净了很多。
实现代码和转载文章大致差不多,做个记录用。
1.策略接口
public interface Strategy {
/**
* 共同行为
* @return
*/
BigDecimal calculatePrice();
}
2.实现接口
/**
* 普通用户
* @author Bowin
*
*/
@Service("generalMember")
public class GeneralMember implements Strategy{
@Override
public BigDecimal calculatePrice() {
return new BigDecimal("100");
}
}
/**
* vip用户
* @author Bowin
*
*/
@Service("vipMember")
public class VipMember implements Strategy{
@Override
public BigDecimal calculatePrice() {
return new BigDecimal("80");
}
}
3.策略控制器(要做异常处理)
/**
* 策略管理器
* @author Bowin
*
*/
@Component
public class StrategyContext {
/**
*使用线程安全的ConcurrentHashMap存储所有实现Strategy接口的Bean
*key:beanName
*value:实现Strategy接口Bean
*/
private final Map<String, Strategy> strategyMap = new ConcurrentHashMap<>();
/**
* 注入所有实现了Strategy接口的Bean
* @param strategyMap
*/
@Autowired
public StrategyContext(Map<String, Strategy> strategyMap) {
this.strategyMap.clear();
strategyMap.forEach((k, v)-> this.strategyMap.put(k, v));
}
/**
* 计算价格
* @param memberLevel 会员等级
* @return 价格
*/
public BigDecimal calculatePrice(String memberLevel) {
//在这里要捕捉异常,或者是做相应处理,因为如果找不到service名字
//会报错,也就是找不到对应的策略
if(!StringUtils.isEmpty(memberLevel)){
return strategyMap.get(memberLevel).calculatePrice();
}
return null;
}
}
4.客户端调用
/**
* 前端控制器
* @author Bowin
*
*/
@Controller
@RequestMapping
public class HelloController {
@Autowired
private StrategyContext strategyContext;
@RequestMapping("calculatePrice")
public @ResponseBody BigDecimal calculatePrice(String memberLevel) {
return strategyContext.calculatePrice(memberLevel);
}
}
5.访问测试:http://localhost:9999/calculatePrice?memberLevel=vipMember 返回 80
这里的vipMember即就是@Service("vipMember")里写的。
其实代码还有一些调优的地方,可以自己去思考一下。
关于这个策略控制器里定义了一个map<String,Strategy>的map,居然它就能自动找到实现了Strategy的所有bean,并将service的beanName作为了key。这个在文章https://blog.youkuaiyun.com/puhaiyang/article/details/86697359里有源码的说明。