場(chǎng)景描述
在我們?nèi)粘i_發(fā)中锉试,經(jīng)常會(huì)有遇到這樣的場(chǎng)景,前端傳一個(gè)標(biāo)識(shí)到后端揍移,后端根據(jù)傳過來標(biāo)識(shí)的不同內(nèi)容次和,做相應(yīng)的業(yè)務(wù)處理;也會(huì)有這樣的場(chǎng)景那伐,后端查詢訂單狀態(tài)踏施,根據(jù)訂單狀態(tài)的不同石蔗,做相應(yīng)的業(yè)務(wù)處理。
因此畅形,我們經(jīng)常會(huì)見到類似下面的代碼:
public void biz(String orderId) {
Order order = orderMapper.getOderById(orderId);
if (order.getBussinessType() == 1) {
//批量開票
} else if (order.getBussinessType() == 2) {
//批量購買工作室
} else if (order.getBussinessType() == 3) {
//單個(gè)開票
} else if (order.getBussinessType() == 4) {
//單個(gè)購買工作室
} else {
System.out.println("業(yè)務(wù)類型無法處理");
}
}
根據(jù)不同的業(yè)務(wù)類型养距,做不同的業(yè)務(wù),使用if else日熬,看起來還挺清晰的棍厌,但是,這樣寫竖席,尤其每個(gè)業(yè)務(wù)類型要處理的事情很多耘纱,代碼很長(zhǎng),那上面這段代碼就會(huì)顯得很臃腫毕荐,并且較難維護(hù)和擴(kuò)展束析。
解決辦法(策略模式)
首先,我們來寫一個(gè)世界上最簡(jiǎn)單的策略模式憎亚,讓我們感受一把什么是策略模式员寇。
//定義策略接口
public interface Strategy {
public int doOperation(int num1, int num2);
}
//策略1
public class OperationAdd implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
//策略2
public class OperationSubtract implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
//策略處理器
public class Context {
private Strategy strategy;
public Context(Strategy strategy){
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2){
return strategy.doOperation(num1, num2);
}
}
public class StrategyPatternDemo {
public static void main(String[] args) {
Context context = new Context(new OperationAdd());
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationSubtract());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
}
}
通過上面的例子,我們基于Spring來仿一個(gè)策略模式第美,重來來達(dá)到我們的需求丁恭。
step1 定義枚舉(后續(xù)要使用到,用于管理多種業(yè)務(wù)類型)
package com.longer.test;
import lombok.Getter;
/**
* 業(yè)務(wù)類型枚舉
* @author Longer
*/
public enum OriginBusinessType {
/**
* 批量開票
*/
BATCH_INVOICE(1, "批量開票", "batchInvoiceSolver"),
/**
* 批量購買工作室
*/
CREATE_STUDIO(2, "批量購買工作室", "batchBuyStudioSolver"),
/**
* 單個(gè)開票
*/
SINGLE_INVOICE(3, "單個(gè)開票", "singleInvoiceSolver"),
/**
* 單個(gè)購買工作室
*/
BUY_STUDIO(4, "單個(gè)購買工作室", "buyStudioSolver");
/**
* 業(yè)務(wù)類型
*/
@Getter
private int code;
/**
* 策略類名(多種策略斋日,每中策略對(duì)應(yīng)一個(gè)類名)
*/
@Getter
private String className;
/**
* 業(yè)務(wù)類型描述
*/
@Getter
private String desc;
OriginBusinessType(int code, String desc, String className) {
this.className = className;
this.code = code;
this.desc = desc;
}
public static String getClassNameByCode(int code) {
String className = "";
OriginBusinessType[] values = OriginBusinessType.values();
for (OriginBusinessType value : values) {
if (value.getCode() == code) {
className = value.getClassName();
}
}
return className;
}
}
step2 定義策略接口
public interface OrderStrategy {
/**
* 執(zhí)行方法
* @param order
*/
void solve(Order order);
}
step3 定義各種策略
/**
* 批量購買工作室
*/
@Component
public class BatchBuyStudioSolver implements OrderStrategy{
@Override
public void solve(Order order) {
System.out.println("執(zhí)行批量購買工作室業(yè)務(wù)");
}
}
@Component
public class BatchInvoiceSolver implements OrderStrategy{
@Override
public void solve(Order order) {
System.out.println("執(zhí)行批量開票業(yè)務(wù)");
}
}
/**
* 單個(gè)購買工作室
*/
@Component
public class BuyStudioSolver implements OrderStrategy{
@Override
public void solve(Order order) {
System.out.println("執(zhí)行單個(gè)購買工作室業(yè)務(wù)");
}
}
/**
* 單個(gè)開票
*/
@Component
public class SingleInvoiceSolver implements OrderStrategy{
@Override
public void solve(Order order) {
System.out.println("單個(gè)開票");
}
}
step4 定義策略處理器
/**
* 策略處理器
*/
@Component
public class OrderStrategySolver implements ApplicationContextAware {
/**
* 策略存儲(chǔ)容器
*/
private Map<String, OrderStrategy> chooseMap = new HashMap<>();
private ApplicationContext context ;
public OrderStrategy getStrategy(String className){
return chooseMap.get(className);
}
/**
* 將各種策略對(duì)象加載進(jìn)chooseMap容器里
*/
@PostConstruct
public void register() {
Map<String, OrderStrategy> solverMap = context.getBeansOfType(OrderStrategy.class);
for (String key : solverMap.keySet()) {
chooseMap.put(key,solverMap.get(key));
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
}
說明:
實(shí)現(xiàn)ApplicationContextAware接口:在服務(wù)啟動(dòng)時(shí)牲览,可以通過applicationContext獲取容器里面的bean。
@PostConstruct:容器加載servlet時(shí)恶守,執(zhí)行該方法第献。
Last 看效果
策略模式代碼寫到這就差不多結(jié)束了。那么現(xiàn)在我們來看看效果:
文章開頭那該死的if esle兔港,現(xiàn)在只用如下一行代碼就可以替代掉了庸毫。
orderStrategySolver.getStrategy(OriginBusinessType.getClassNameByCode(order.getBussinessType())).solve(order);