优点:
1:接口开闭原则,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为;
2:算法的使用就和算法本身分开,符合“单一职责原则”;
3:策略类的复用;
缺点:
1:策略模式将造成系统产生很多具体策略类,代码量增多;
2:在使用策略模式时,每次只能使用一个策略类
注意:由于代码方便阅读,金额没有使用BigDecimal,没有使用枚举代替常量
策略模式第一阶段:实现策略模式
public Double getPriceByCustomerType(String customerType) {
Double originalPrice = 100.00;
//策略接口
ICustomerQuotation quotation;
//在if-else中 仅负责 新建对象 即是选择不同的逻辑
//根据类型用户类型 new 一个实现策略接口的 策略实现类对象(里面是不同逻辑实现)
if ("新用户".equals(customerType)) {
quotation = new NewCustomerQuotation();
} else if ("老用户".equals(customerType)) {
quotation = new OldCustomerQuotation();
} else if ("Vip用户".equals(customerType)){
quotation = new VIPCustomerQuotation();
} else {
quotation = new NewCustomerQuotation();
}
//通过使用 策略实现类对象 在上下文的类中去使用该对象
CustomerQuotationContext customerQuotationContext = new CustomerQuotationContext(quotation);
//使用该上下类的方法 这个时候已经会在里面调用 策略实现类对象的方法了
return customerQuotationContext.getPrice(originalPrice);
具体代码与目录结构:
//策略抽象类
public interface ICustomerQuotation {
//抽象方法
Double getPriceQuotation(Double originalPrice);
}
//策略实现类
public class NewCustomerQuotation implements ICustomerQuotation {
//实现方法
@Override
public Double getPriceQuotation(Double originalPrice) {
return originalPrice*0.9;
}
}
//上下文类 引入策略实现类并使用其方法
public class CustomerQuotationContext {
private ICustomerQuotation quotation;
//引入 策略对象
public CustomerQuotationContext(ICustomerQuotation quotation) {
this.quotation = quotation;
}
//使用 策略对象
public Double getPrice(Double originalPrice) {
log.info("处理前金额:{}",originalPrice);
Double price = quotation.getPriceQuotation(originalPrice);
log.info("处理后金额:{}",price);
return price;
}
}
Strategy类图分析
策略模式第二阶段:去除完全去除 If-Else
//修改 策略抽象类
public interface ICustomerQuotation {
//抽象方法
Double getPriceQuotation(Double originalPrice);
//新建Map
public static Map<String,ICustomerQuotation> strategyMap
= new ConcurrentHashMap<>();
//新增获取Type
public String getCustomerType();
// 整体执行顺序 Constructor ->@Autowired->@PostConstruct(注解的方法)
@PostConstruct
default public void initStrategy(){
strategyMap.put(getCustomerType(),this);
}
}
initStrategy讲解
@PostConstruct (后续有截图)
//策略实现类交给Spring管理
//执行策略实现类的构造方法
//通过反射执行后面的方法
//在invoke 后面的方法有一个判断@PostConstruct
// 进入后 在invoke中执行加了 @PostConstruct注解的方法
default public void initStrategy()
//initStrategy()在实现类中是已经默认实现了
//实现类会继承接口中的default方法 (JKD1.8 新特性 default)
strategyMap.put(getCustomerType(),this);
//使用该方法的时候,
//1:已经调用了实现类的getCustomerType()方法
//2:返回 策略实现类对象
//3:策略类型作为key值 策略实现类对象作为Value存放在map中
//策略实现的Bean交给Spring管理
@Service
public class NewCustomerQuotation implements ICustomerQuotation {
//实现方法
@Override
public Double getPriceQuotation(Double originalPrice) {
return originalPrice*0.9;
}
//实现新方法 getCustomerType
@Override public String getCustomerType() {
return "新用户"; }
}
}
//注意 :上下文接口完全不变
//public class CustomerQuotationContext
//修改主方法 直接通过 customerType获取 策略对象
public Double getPriceByCustomerType(String customerType) {
Double originalPrice = 100.00;
//此时已经会获取到所有的strategyMap
log.info("获取到的strategyMap: {}",
JSONObject.toJSONString(ICustomerQuotation.strategyMap));
//策略接口
ICustomerQuotation quotation
=ICustomerQuotation.strategyMap.get(customerType);
//避免获取不到类型对应的策略对象
if(quotation == null){
quotation = new NewCustomerQuotation();
}
后面不变,使用上下文类 直接使用策略对象 quotation 即可
Spring管理中@PostConstruct的使用
完全去除If-Else方法 之后每新增一种策略类型 则新增一个实现类即可
了解
ThreadPoolExecutor的策略:
RejectedExecutionHandler(当线程池慢时:拒绝策略):
ThreadPoolExecutor.
1:DIscardOldestPolicy(抛弃队列里面等待最久的一个线程)
2:DiscardPolicy(对拒绝任务直接无声抛弃,没有异常信息)
3:CallerRunPolicy(多开一个线程)
4:AbortPolicy(对拒绝任务抛弃处理,并且抛出异常)
corePoolSize : 线程池维护线程的最少数量,哪怕是空闲的。
maximumPoolSize :线程池维护线程的最大数量。
workQueue : 线程池所使用的缓冲队列,决定了能够缓冲的最大数量。
- 如果此时线程池中的数量小于 corePoolSize ,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
- 如果此时线程池中的数量等于 corePoolSize ,但是缓冲队列 workQueue 未满,那么任务被放入缓冲队列。
- 如果此时线程池中的数量大于 corePoolSize ,缓冲队列 workQueue 满,并且线程池中的数量小于maximumPoolSize ,建新的线程来处理被添加的任务。
- 如果此时线程池中的数量大于 corePoolSize ,缓冲队列 workQueue 满,并且线程池中的数量等于maximumPoolSize ,这时 handler 所指定的策略来处理此任务。