【Spring原始碼解析】—— 策略模式在Spring中的應用
一、 什麼是策略模式
策略模式的定義/含義:策略本身就是為了實現某一個目標而採取的一種工作方式,因此只要能夠達成目標,則採取哪一種策略都可以;因此多種實際的策略之間是相互平行的。
注意:策略模式與模板模式是不同的,模板模式是定義了一個骨架(會有很多個步驟,其中可能包含必選和可選步驟,步驟之間可能會有一定的順序,模板模式在頂級骨架中可能會有部分實現,也可將部分實現延遲到子類中,例如:TestCase的過程,一般都包含setUp、testCase、tearDown操作,testCase需要子類自行實現,setUp和tearDown可以直接通過super來進行呼叫;備註:模板模式後面會再專門整理,可能該部分內容會做更新),模板模式整體構成了一個完整的過程/演算法,可對其中的某些步驟進行自行定製處理,而策略模式是呼叫者獨立於具體的策略演算法,每一種具體策略自身就是完整的,策略A與策略B之間可以自行替換,對呼叫者來說,不關注具體是通過策略A實現的還是B實現的,通過引用傳入上下文,即可按照策略執行達到目標(策略可以理解為:殊途同歸)
因此,在很多場景下都可以使用到策略模式,以大家熟悉的業務場景為例:比如支付方式的選擇。
在Spring中,例項化物件的時候用到了Strategy模式,圖示如下所示:
在上圖中:InstantiationStrategy為抽象介面,SimpleInstantiationStrategy實現介面,但是在方法instantiate中進行判斷,針對bd中沒有MethodOverrides的,直接通過jdk反射進行建構函式呼叫,而針對有需要針對方法做MethodOverrides的,則可以通過另一種方式處理,在SimpleInstantiationStrategy中是通過:instantiateWithMethodInjection()方法處理的,在CglibSubclassingInstantiationStrategy中對該方法做了override實現。CglibSubclassingInstantiationStrategy繼承自SimpleInstantiationStrategy,對MethodInjection方法的實現如下:
@Override protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, @Nullable Constructor<?> ctor, Object... args) {
// Must generate CGLIB subclass... return new CglibSubclassCreator(bd, owner).instantiate(ctor, args); }
通過static的class類CglibSubclassCreator進行instantiate操作,剩下的就是cglib內中的細節了,此處不分析。
策略模式中包含的部分是:(1)抽象策略InstantiationStrategy介面
(2)具體策略SimpleInstantiationStrategy,被繼承後子類CglibSubclassingInstantiationStrategy,實現自抽象策略介面(3)上下文對策略的引用,在AbstractAutowireCapableBeanFactory中是通過new CglibSubclassingInstantiationStrategy賦值給InstantiationStrateg的引用,進而進行具體的方法呼叫,具體見下方程式碼:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { /** Strategy for creating bean instances. */ private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();}
(注意:這裡一般是通過對抽象策略介面的引用,之後通過多實現的根據當時具體選擇的策略內容進行呼叫實現)
二、 自寫demo示例
根據上面提到的策略模式中需要的內容進行demo的編寫,分別是:抽象介面、具體實現、上下文引用及效果展示:
抽象介面定義:
package strategytest.demo; public interface Strategy { PayInfo payForSometh(); }
其中PayInfo定義如下:
package strategytest.demo; public class PayInfo { String payType; String payCode; String payDesc; public PayInfo(String payType, String payCode, String payDesc) { this.payType = payType; this.payCode = payCode; this.payDesc = payDesc; } public String getPayType() { return payType; } public String getPayDesc() { return payDesc; } public String getPayCode() { return payCode; } }
具體策略介面實現:
package strategytest.demo; public class ZhiFuBaoPay implements Strategy { @Override public PayInfo payForSometh() { System.out.println("呼叫支付寶支付功能,根據返回值進行PayInfo類資訊的設定"); PayInfo zhifubaoPayInfo= new PayInfo("支付寶", "0", "支付成功"); return zhifubaoPayInfo; } }
多個具體策略介面實現方式與上類似
上下文引用:
package strategytest.demo; public class StrategyUse { public static void main(String[] args) { Strategy strategy = new WeiXinPay(); PayInfo payinfo = strategy.payForSometh(); System.out.println(payinfo.getPayType() + "," + payinfo.getPayCode() + "," + payinfo.getPayDesc()); } }
結果如下:
參考文章:Spring中的各種模式的介紹:https://www.jianshu.com/p/3ea48ecd7178 ——》這是策略模式的,然後也有其他的模式,都可作為