策略模式Strategy 定義:定義一系列的算法,把它們一個個封裝起來,而且使它們可相互替換。本模式使得算法可獨立於使用它的客戶而變化。策略模式的重心不是如何實現算法,而是如何組織、調用這些算法,從而讓程序結構更靈活、可維護、可擴展。 策略算法對算法調度具備平等性,算法僅僅是一種性質相同而行爲不一樣的處理,地位相同,可相互替換,算法之間沒有依賴關係。 算法
—抽象策略角色: 策略類,一般由一個接口或者抽象類實現。
—具體策略角色:包裝了相關的算法和行爲。
—環境角色:持有一個策略類的引用,最終給客戶端調用。 服務器
策略模式UML圖示
應用場景:
一、 多個類只區別在表現行爲不一樣(性質同樣,但行爲不一樣),可使用Strategy模式,在運行時動態選擇具體要執行的行爲。
二、 須要在不一樣狀況下使用不一樣的策略(算法),或者策略還可能在將來用其它方式來實現(動態)。
三、 對客戶隱藏具體策略(算法)的實現細節(只公開一個功能,隱藏此功能實現的細節),彼此徹底獨立。
this
策略模式之惑 spa
誰來選用策略模式?有2種狀況:調用者,調用者選擇具體的策略算法 ,而後把這個策略算法設置給上下文(發工資示例);服務者,由上下文(服務器端)選擇具體的策略算法(容錯恢復示例)。 .net
策略模式擴展問題 翻譯
針對調用策略模式的2種角色差別,對策略模式的擴展也不盡相同。 設計
(1)對由調用者(客戶端)調用的策略模式,具體的作法是:先寫一個策略算法類來實現新的要求,而後在客戶端使用的時候指定使用新的策略算法類就能夠了。《參見:橋接模式(單緯度的)》 code
(2)對服務端調用的策略模式,以容錯恢復爲例,能夠將Context使用工廠方法(Context裏作的是策略選擇,能夠經過改造實現動態配置)。 對象
=================================================================== 繼承
裝飾模式Decorator
定義:在沒必要改變原類文件和使用繼承的狀況下,動態的擴展一個對象的功能。它是經過建立一個包裝對象,也就是裝飾來包裹真實的對象。實用了用一個對象去包含另外一個對象的目的,這樣就容許用戶動態的向一個對象中添加額外的功能,並且最重要的是,這2種對象是徹底獨立的,並且是同質的(繼承……)。
特色:(1) 裝飾對象和真實對象有相同的接口。這樣客戶端對象就能夠和真實對象相同的方式和裝飾對象交互。(2) 裝飾對象包含一個真實對象的引用(reference)(3) 裝飾對象接受全部來自客戶端的請求。它把這些請求轉發給真實的對象。(4) 裝飾對象能夠在轉發這些請求之前或之後增長一些附加功能。這樣就確保了在運行時,不用修改給定對象的結構就能夠在外部增長附加的功能。在面向對象的設計中,一般是經過繼承來實現對給定類的功能擴展。
裝飾模式:Decorator常被翻譯成「裝飾」,我以爲翻譯成「油漆工」更形象,油漆工(decorator)是用來刷油漆的,那麼被刷油漆的對象咱們稱爲Decoratee,這兩個實體在Decorator模式中是必須的。
Decorator模式定義:
動態給一個對象添加一些額外的職責,就像在牆上刷油漆。使用Decorator模式相比用生成子類方式達到功能的擴展顯得更加靈活。
爲何使用Decorator?
咱們一般可使用繼承來實現功能的擴展,若是這些須要擴展的功能種類繁很繁多,那麼必生成不少子類,增長系統的複雜性,同時,使用繼承實現功能擴展,咱們必須可預見這些擴展功能,這些功能是編譯時就肯定了,是靜態的。
使用Decorator的理由是:這些功能須要由用戶動態決定加入的方式和時機,Decorator提供了「即插即用」的方法,在運行期間決定什麼時候增長何種功能。
如何使用?
咱們先創建一個接口:
public interface Work { public void insert(); }
接口Work又一個具體實現:插入方形樁或圓形樁,這兩個區別對Decorator是無所謂。咱們以插入方形樁爲例:
public class SquarePeg implements Works { public void insert() { System.out.println("方形樁插入"); } }
如今有一個應用,須要在樁打入前,挖坑,在打入後,在樁上釘木板,這些額外功能是動態,能夠隨意增長調整修改。
那麼咱們使用Decorator模式,這裏方形樁SquarePeg是decoratee,咱們須要在decoratee上刷些漆,這些油漆就是那些額外的功能。
public class Decorator implements Work { private Work work; public Decorator(Work work) { this.work = work; } public insert() { beforeInsert(); work.insert(); afterInsert(); } public beforeInsert() { } public afterInsert() { } }
裝飾模式就這樣出來,咱們如何調用:
Work squarePeg = new SequarePeg(); Work decorator = new Decorator(squarePeg); decorator.insert()