策略模式和模板方法同與異


前言:

  最近在寫項目的時候,深感設計模式的重要性。一個人的代碼寫的好不好,別人看的舒不舒服,和會不會設計模式緊密關聯的。之前看過四人幫的設計模式。但當時僅限於看,包括現在也僅限於看。有的時候項目中,你都不知道有沒有運用到了設計模式。也許用到了單例模式,但你並不知道如何用的,不知不覺就用到了。

  《武林外傳》老白曾經說過這樣一句話。高手就是手里無刀,心中也無刀。類似於設計模式,你不知不覺中已經融進你的代碼中了,但你並不知已經運用了。當然我沒有達到這個境界,可能五年,十年,或者更久,誰也說不准呢。

  這次正好趁這個項目,把用到的涉及模式總結一下,策略模式和模板方法模式。

 

1:設計模式分類

總體來說設計模式分為三大類:

創建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。

結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。

行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。

我們這次講的都屬於行為型模式。這類模式負責對象間的高效溝通和職責委派。注意理解下對象間,責任委派。

 

2:策略模式

策略模式是一種行為設計模式 它能讓你定義一系列算法 並將每種算法分別放入獨立的類中 以使算法的對象能夠相互替換

在我的項目中有這么一個場景,大家也可以想象一個。用戶購買商品支付的時候,可能會使用多種不同的優惠券。比如說,貼息,滿減,隨機立減等等

這幾種返回給前端的金額,文案,以及個個方法都有比較大的差異。我們可以理解為三種不同的算法,選擇哪種策略,完全由用戶有哪張優惠券所決定的。

因此很簡單的,我們可以使用策略模式。

1: 我們首先先定義一個接口

1 @Service
2 public interface CouponStrategy {
3 
4     void execute(Coupon coupon);
5 
6 }

2:定義不同的實現類

 1 class CouponStrategyA implements CouponStrategy {
 2 
 3     @Override
 4     public void execute(Coupon coupon) {
 5         // 第一種具體算法
 6     }
 7     
 8 }
 9 
10 class CouponStrategyB implements CouponStrategy {
11 
12     @Override
13     public void execute(Coupon coupon) {
14         // 第二種具體算法
15     }
16     
17 }

3:我們可以根據coupon選擇不同的算法。這里我們可以采用工廠模式

 1 @Service
 2 public class CouponStrategyFactory {
 3 
 4     
 5     private Map<String, CouponStrategy> serviceMap = new HashMap<>();
 6 
 7     
 8     public CouponStrategy getService(CouponInfo couponInfo) {
 9 
10         CouponStrategy couponStrategy = serviceMap.getOrDefault(coupon.getCouponType(), couponDefault);
11 
12         return couponStrategy;
13     }
14 
15 }

最后,這種算法看起來是非常的干凈整潔舒服的。比如之前很多type=1,則算法A。type=2則算法B。代碼雖然實現,但看起來很難受。

並且策略模式讓你能將不同行為抽取到一個獨立類層次結構中 並將原始類組合成同一個 從而減少重復代碼。比如我可以把A,B,C算法重復的都抽象到interface接口中,代碼最重要一點就是避免寫重復性的代碼。

 

3:模板模式

模板方法模式是一種行為設計模式 它在超類中定義了一個算法的框架 允許子類在不修改結構的情況下重寫算法的特定步驟

比如我們JDK經典的ArrayList,用到的就是模板模式,我們看一下他的類圖如下:

 

 

這幅圖真的特別的經典,可以說是學習模板方法最好的實踐了。

ArrayList繼承了AbstractList並且實現了多種的接口。ArrayList只實現了自己特定的算法,其余比較通用的算法全部由AbstractList實現。

比如addAll方法, 它位於absract接口。它定義了一系列的算法,比如首先check,在for循環add等等。

但是具體怎么add他並沒有實現,而是交由子類去具體實現。

1 public boolean addAll(int index, Collection<? extends E> c) {
2     rangeCheckForAdd(index);
3     boolean modified = false;
4     for (E e : c) {
5         add(index++, e);
6         modified = true;
7     }
8     return modified;
9 }

比如ArrayList的實現

1 public void add(int index, E element) {
2     rangeCheckForAdd(index);
3 
4     ensureCapacityInternal(size + 1);  // Increments modCount!!
5     System.arraycopy(elementData, index, elementData, index + 1,
6                      size - index);
7     elementData[index] = element;
8     size++;
9 }

又比如LinkedList

1 public void add(int index, E element) {
2     checkPositionIndex(index);
3 
4     if (index == size)
5         linkLast(element);
6     else
7         linkBefore(element, node(index));
8 }

類似於子類可以通過鈎子操作可以控制父類的行為,是不是很神奇。

最后,當你只希望客戶端擴展某個特定算法步驟 而不是整個算法或其結構時 可使用模板方法模式 模板方法將整個算法轉換為一系列獨立的步驟 以便子類能對其進行擴展 同時還可讓超類中所定義的結構保持完整

 

4:策略模式和模板模式同與異

這兩種模式非常的相像,一不留神可以分不清楚用那種模式了。當然這就是開頭所說的,心中有刀,手里已無刀,你不知不覺中已經融進你的代碼中了,但你並不知已經運用了。這其實就是最棒的結果了,但對於咱們初學者,剛開始弄清楚還是有必要的。

相同點:

1: 毋庸置疑都可以減少代碼的重復,將重復代碼抽象到父類即可。

2: 可以很容易的切換算法,根據前端傳來的參數,具體算法何種算法,何種模式。

 

不同點:

1:模板模式基於繼承機制 它允許你通過擴展子類中的部分內容來改變部分算法

2:策略模式基於組合機制 你可以通過對相應行為提供不同的策略來改變對象的部分行為 模板方法在類層次上運作 因此它是靜態的 策略在對象層次上運作 因此允許在運行時切換行為

3:模板更加看重是算法的流程,全部已經規定好了,子類可以修改部分流程算法

4:策略模式是將整個算法全部重寫,不是部分,而是整體。

 

最后祝大家都能寫出漂亮,驚艷,眼前一亮的代碼。最終做到,手里無刀,心中也無。

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM