JAVA設計模式-策略模式及在Springboot2.X中寫法
- 一、經典的策略模式寫法
- 二、Springboot2.X中策略模式寫法
策略模式的定義:策略模式是一種行為型設計模式,定義了一系列算法,并將每個算法封裝起來,使它們可以互相替換
策略模式:在策略模式(Strategy Pattern)中,一個類的行為或其算法可以在運行時更改。這種類型的設計模式屬于行為型模式。
在策略模式中,我們創建表示各種策略的對象和一個行為隨著策略對象改變而改變的 context 對象。策略對象改變 context 對象的執行算法。
主要解決:在有多種算法相似的情況下,使用 if…else 所帶來的復雜和難以維護。
何時使用:一個系統有許多許多類,而區分它們的只是他們直接的行為。
如何解決:將這些算法封裝成一個一個的類,任意地替換。
關鍵代碼:實現同一個接口。
應用實例: 1、諸葛亮的錦囊妙計,每一個錦囊就是一個策略。 2、旅行的出游方式,選擇騎自行車、坐汽車,每一種旅行方式都是一個策略。 3、JAVA AWT 中的 LayoutManager。
策略模式三種角色:
- 1、環境上下文(Context)角色:持有一個Strategy引用,委托策略變量調用具體策略所實現的策略接口中的方法。
- 2、策略(Strategy)角色:抽象角色,通常由一個接口或抽象類實現,此角色給出所有的具體策略類所需接口。
- 3、具體策略(ConcreteStrategy)角色:具體實現策略接口的類,包裝了相關的算法或行為。
一、經典的策略模式寫法
/*** 策略接口*/
public interface Strategy {int doOperation(int num1, int num2);
}/*** 加法策略*/
class OperationAdd implements Strategy {@Overridepublic int doOperation(int num1, int num2) {return num1 + num2;}
}/*** 減法策略*/
class OperationSub implements Strategy {@Overridepublic int doOperation(int num1, int num2) {return num1 - num2;}
}/*** 策略上下文類*/
class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public Strategy getStrategy() {return strategy;}public void setStrategy(Strategy strategy) {this.strategy = strategy;}public int executeStrategy(int num1, int num2) {return strategy.doOperation(num1, num2);}
}class Main{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 OperationSub());System.out.println("10 - 5 = " + context.executeStrategy(10, 5));}
}
但是上述的寫法中,在具體使用過程中,要需要new具體的策略,而不能簡單的傳輸一些字段來實現
二、Springboot2.X中策略模式寫法
參考鏈接
在springboot中實現的時候可以采用@Component來標記為bean,通過獲取bean來直接得到想要的具體策略
下述例子采用數據庫存儲的方式,將具體的code和beanId關聯在一起,通過code–>獲取beanId–>獲取bean–>執行bean,從而不需要在Context中寫if-else,或者在調用過程中寫死new具體的策略
同理,使用 讀取緩存、讀取枚舉、讀取數據庫等方式來實現,一定程度上解耦了抽象類和實體類之間的關聯。
1.首先定義策略模式的策略接口
public interface Strategy {int doOperation(int num1, int num2);
}
2.定義具體的策略
在springboot中可以使用@Component標記一個類為組件
實現加法策略
@Component
public class OperationAdd implements Strategy {@Overridepublic int doOperation(int num1, int num2) {return num1 + num2;}
}
實現減法策略
@Component
class OperationSub implements Strategy {@Overridepublic int doOperation(int num1, int num2) {return num1 - num2;}
}
3.實現環境上下文Context
@Component
public class ContextStrategy {@Resourceprivate OperatorMapper operatorMapper;public int executeStrategy(int code,int num1, int num2) {OperatorEntity entity = OperatorMapper.getOperator(code);Strategy strategy = SpringUtils.getBean(entity.getStrategyBeanId(),Strategy.class);return strategy.doOperation(num1, num2);}
}
4.使用
@RestController
public class OperatorController {@Autowiredprivate ContextStrategy contextStrategy;@GetMapping("/toDoOperator")public String toDoOperator(String code,int num1,int num2){return contextStrategy.doOperation(code,num1,num2);}
}
5.細節部分
注意:這里有個細節問題,數據庫存儲的beanId一定要跟我們定義的bean保持一致,否則根據beanId去spring容器中獲取實例對象會失敗!
附根據beanId獲取對應實例對象的utils
/*** 根據beanId 從spring容器中獲取對象*/
@Component
public class SpringUtils implements ApplicationContextAware {private static ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}//獲取applicationContextpublic static ApplicationContext getApplicationContext() {return applicationContext;}//通過name獲取 Bean.public static Object getBean(String name){return getApplicationContext().getBean(name);}//通過class獲取Bean.public static <T> T getBean(Class<T> clazz){return getApplicationContext().getBean(clazz);}//通過name,以及Clazz返回指定的Beanpublic static <T> T getBean(String name,Class<T> clazz){return getApplicationContext().getBean(name, clazz);}}