策略模式做爲一種軟件設計模式,指對象有某個行爲,可是在不一樣的場景中,該行爲有不一樣的實現算法。(維基百科)java
概念中說策略模式是某個行爲在不一樣場景下有不一樣的實現算法。咱們知道有一條設計原則是這樣的:分離變化的部分和不變的部分。在這個概念中咱們能夠知道。不變的地方,是這個行爲,變化的,是執行這個行爲所須要的算法,或者說是策略。算法
這個模式的應用場景應該是這樣的。咱們須要對若干個均可以實現咱們所要的功能中選擇一個最合適的。舉一個簡單的例子:java君、Pascal君、Scala君三我的要去餐廳吃飯。但是呢,他們仨我的的口味不同,java君想吃麪向對象大餐,Pascal君想吃麪向過程大餐,而Scala君想吃函數式大餐,這時候假設你是餐廳服務員,你給每一個人點餐的時候,就要這樣寫了spring
if(pascal君) return 面向過程大餐;else if(java君)return 面向對象大餐;else if(scala君)return 函數式大餐;
這就太糟了。由於若是又來了一個spring先生想要吃aop大餐,就要去更改源碼了。這不符合咱們「對修改關閉,對擴展開放」的原則。因此這種設計是不行的。編程
咱們說要分離開變化的和不變的東西。變化的就是對不一樣的人要上不一樣的菜。咱們把這一點從代碼中分離出來。單獨封裝起來。利用多態,給每一類人一個點某種菜的能力。咱們可讓全部人實現一個Order接口,這個接口中定義了點菜這個方法,讓每一個人都去實現這個方法,而後在點菜的時候直接去調用每一個人的order方法。這樣若是在來新的人的話,咱們不用改動原有的代碼,只須要讓新人實現本身的order方法就能夠。這樣就符合設計原則了。下面是實現代碼。設計模式
/* * Created by 王鏡鑫 on 2016/10/7 */ interface Order//點餐接口 { public void order();//點餐方法 } class JAVA implements Order//java君實現點餐接口 { public void order() { System.out.println("I want a Object Oriented meal"); } } class Pascal implements Order//Pascal君實現點餐接口 { public void order() { System.out.println("I want a Procedure Oriented meal"); } } class Scala implements Order//Scala君實現點餐接口 { public void order() { System.out.println("I want a functional meal"); } } public class Restaurant//餐廳 { private Order order = null; public void setOrder(Order order)//設置點餐的人。 { this.order = order; } public void order()//讓點餐人點餐 { order.order(); } public static void main(String[] args) { Restaurant restaurant = new Restaurant();//實例化一個餐廳 restaurant.setOrder(new JAVA());//將java君設置進去 restaurant.order();//讓java君點餐 restaurant.setOrder(new Pascal());//將Pascal君設置進去 restaurant.order();//讓Pascal君點餐 restaurant.setOrder(new Scala());//將Scala君設置進去 restaurant.order();//讓Scala君點餐 } }
輸出以下:函數
I want a Object Oriented meal I want a Procedure Oriented meal I want a functional meal
可見,java君、Pascal君、Scala君都吃到了本身想吃的大餐。而且及時再來一個彙編先生,咱們也不怕,也不用修改原來的代碼。只須要在添加一個彙編先生類讓其實現點餐接口就能夠了。this
咱們經過一個例子。來描述了所謂的策略模式的應用場景,和如何應用策略模式解決問題,使代碼更易擴展,下降耦合。下面咱們總結一下策略模式。
經過上面的例子,咱們得知,策略模式包含如下角色:spa
三者的關係以下圖:scala
上下文中有一個策略屬性,還有一個設置策略的方法,一個工做方法。工做方法中實現的就是策略的工做方法。 具體的策略A和具體的策略B去實現了策略接口,實現了work方法。這樣在調用上下文的work方法,就是調用了實際設置的具體策略的work方法,從而實現了將執行策略與具體的策略解耦,有新的策略的時候,只須要再從新聲明一個策略類就能夠。
策略模式是一種很是簡單的設計模式,策略模式是對不一樣的算法的封裝,把算法的責任和算法自己分離開來,將算法委派給不一樣的對象管理,用一句話來講,策略模式就是:實現一族算法,並將每個算法都封裝起來,使其相互交換。
策略模式中,使用哪種策略是由用戶來決定的,這提升了系統的靈活性,可是這在必定程度上,也增長了客戶端的使用難度。由於客戶端須要瞭解不一樣的算法之間的區別,選擇合適的算法。策略模式還體現了這樣一個設計原則:針對接口編程,而不是針對實現編程。咱們在策略模式中,用一個接口表明行爲,根據多態,上下文在工做時執行的行爲,是這個接口的具體實現。思考咱們經常使用的jdk官方的排序方法。Colloctions.sort(List<T> list)和他的重載方法 sort(List<T> list, Comparator<? super T> c)他們的實現都是直接調用了List的sort方法,區別是一個傳入的比較器是null,一個是傳入了具體的比較器,比較器是null的那個方法,list中的元素T也是實現了Comparablel接口的。這就是一個典型的策略模式的應用。再排序的時候,因爲不一樣的須要排序的類的排序規則不同,也就是策略不同,因此咱們把策略封裝到客戶部分,也就是具體須要排序的類中,也就是讓具體須要排序的類實現Comparable接口,而後在傳入到排序的算法中的時候,排序的算法在比較兩個元素的前後順序的時候直接調用其compareTo方法,根據多態,他調用的實際上是具體傳入的compareTo方法。也就是封裝到子類中的具體的比較策略,這樣就能實現了具體的排序。這是策略模式在排序中的應用。
因爲知識水平有限,文章中有疏漏或者錯誤的地方,歡迎你們留言指正。設計