設計模式 -- 政策模式+Spring Bean代替if/else

政策模式
一、什麼是政策模式
- 政策模式屬于對象的行為模式。其用意是針對一組算法,将每一個算法封裝到具有共同接口的獨立的類中,進而使得它們可以互相替換。政策模式使得算法可以在不影響到用戶端的情況下發生變化。
二、政策模式的結構
- 政策模式是對算法的包裝,是把使用算法的責任和算法本身分割開來,委派給不同的對象管理。政策模式通常把一個系列的算法包裝到一系列的政策類裡面,作為一個抽象政策類的子類。用一句話來說,就是:“準備一組算法,并将每一個算法封裝起來,使得它們可以互換”。下面就以一個示意性的實作講解政策模式執行個體的結構。
這個模式涉及到三個角色:
● 環境(Context)角色:持有一個Strategy的引用。
● 抽象政策(Strategy)角色:這是一個抽象角色,通常由一個接口或抽象類實作。此角色給出所有的具體政策類所需的接口。
● 具體政策(ConcreteStrategy)角色:包裝了相關的算法或行為。
使用政策模式完美的解決了我們if else 太多導緻代碼臃腫的問題 如:
if(teachinType == 1){
……
}else if(teachinType == 2){
……
}else{
}
三、實戰
介紹:在我們項目實戰中,我們通常會遇到 我們背景拿到前端傳來的參數走不同的邏輯 (線上 ,線下 業務 ) ,傳回相同的資料結構:
if(teachinType == 1){
……
return list<Integer>;
}else if(teachinType == 2){
……
return list<Integer>;
}else{
……
return list<Integer>;
}
普通政策模式
- 定義接口
public interface Type {
/**
* 擷取類型,傳回集合
*/
List<Integer> getType();
}
- 定義OfflineType實作類實作Type
@Service
public class OfflineType implements Type {
@Override
public List<Integer> getType() {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
return list;
}
}
- 定義OnlineType實作類 實作Type接口
@Service
public class OnlineType implements Type {
@Override
public List<Integer> getType() {
List<Integer> list = new ArrayList<>();
list.add(3);
list.add(4);
return list;
}
}
- 定義政策工廠類
public class TypeFactory{
private static TypeFactory typeFactory = new TypeFactory();
//定義Map
private static Map<Integer,Type> map = new HashMap<>();
static{
map.put(1,new OfflineType());
map.put(2,new OnlineType())
}
public static TypeFactory getInstance(){
return typeFactory;
}
public Type getByType(Integer type){
return map.get(type);
}
}
- 使用
@GetMapping("list")
public List<Integer> list(@ApiParam(value ="類型")@RequestParam(required = false) Integer type) {
return TypeFactory.getInstance().getByType(type).getType();
);
接口測試輸入1,輸出 1,2
接口測試輸入2,輸出 3,4
政策模式+Spring Bean代替if/else
- 在上面政策模式中如果在實作類中使用
@Autowired
private Dao dao;
就會出現 空指針的情況,
java.lang.NullPointerException
因為 發現政策實作中的Dao接口注入的都是Null。
我們回頭看spring源碼 以及 他的介紹
- 必須在所有使用了dao的地方,包括調用它的servcie都要進行@Autowired注入,否則之後的注入就會失敗
- 順着這句話,發現上述使用處不就沒使用@Autowired進行注入嗎?但是這個政策模式得new啊?
- 我們還有其他方式:通過給實作類起别名,通過@Qualifier注解擷取不同的實作類
改造:
實作類
@Service("offlineType")
public class OfflineType implements Type {
@Autowired
private OfflineDao dao;
@Override
public List<Integer> getType() {
return dao.selectList();
}
}
@Service("onlineType")
public class OnlineType implements Type {
@Autowired
private OnlineDao dao;
@Override
public List<Integer> getType() {
return dao.selectList();
}
}
工廠
public class TypeFactory{
@Resource
@Qualifier("offlineType")
private OnlineType offlineType;
@Resource
@Qualifier("onlineType")
private OnlineType onlineType;
public Type getByType(Integer type){
Map<Integer, Type> map =new HashMap<>();
map.put(1,offlineType);
map.put(2,onlineType);
return map.get(type);
}
}
// 工廠注入
@Autowired
private TypeFactory typeFactory;
@GetMapping("list")
public List<Integer> list(@ApiParam(value ="類型")@RequestParam(required = false) Integer type) {
return typeFactory.getByType(type).getType();
);
發現 不會出現空指針,IOC正常注入,資料正常傳回
個人部落格:
http://blog.yanxiaolong.cn/