1. 策略模式的做用java
在策略模式(Strategy Pattern)中,一個類的行爲或其算法能夠在運行時更改。算法
2. 爲何要使用策略模式?ide
咱們想象一下最多見的場景:排序。排序無非兩種選擇,升序或降序。若是咱們要封裝一個類要自由的切換兩種排序要怎麼作呢?函數
最多見的作法是這樣的:this
public class Demo { public void sort(boolean asc) { if (asc) { //判斷是否要升序 //實現升序的算法 } else { //實現降序的算法 } } }
咱們能夠發現這要的代碼極不美觀,並且這仍是隻有兩種狀況的時候,加入有N中狀況那豈不是要寫不少的判斷。甚至可能大多數時候咱們並不能提早想好全部的類型,若是臨時要加入新的算法只能再次修改原來的代碼。維護很困難。這時候咱們就可使用策略模式來實現。spa
3. 怎麼使用策略模式?code
以上述排序爲例,在java中咱們須要實現本身的比較器。對象
public static void main(String[] args) { List<Integer> list = new ArrayList<>(); Collections.sort(list, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1 - o2; } }); }
如此,當咱們在須要定義新的排序規則(由於排序的對象多是多種多樣的),當咱們須要一個新的規則時,咱們不須要去修改Collections.sort()方法的內容,而是實現一個本身的比較器,這樣就能夠實現新的排序。blog
4. 分析一下策略模式是怎麼構成的?排序
咱們一樣以上述排序爲例:
(1)策略接口
@FunctionalInterface public interface Comparator<T> { 這是策略接口
int compare(T o1, T o2); 這是實現不一樣策略的接口函數
(2)不一樣的實現
class MyComparator4Integer implements Comparator{ //爲了比較Integer類型而實現的類 @Override public int compare(Object o1, Object o2) { return 0; } }
class MyComparator4String implements Comparator{ //爲了比較String類型而實現的類
@Override
public int compare(Object o1, Object o2) {
return 0;
}
}
(3)調用者中(其中一個
private static <T> void binarySort(T[] a, int lo, int hi, int start, Comparator<? super T> c) { assert lo <= start && start <= hi; if (start == lo) start++; for ( ; start < hi; start++) { T pivot = a[start]; // Set left (and right) to the index where a[start] (pivot) belongs int left = lo; int right = start; assert left <= right; /* * Invariants: * pivot >= all in [lo, left). * pivot < all in [right, start). */ while (left < right) { int mid = (left + right) >>> 1; if (c.compare(pivot, a[mid]) < 0) //在調用者中會調用策略函數,當傳入的比較器不一樣時,比較的規則也會隨之改變 right = mid; else left = mid + 1; } assert left == right; /* * The invariants still hold: pivot >= all in [lo, left) and * pivot < all in [left, start), so pivot belongs at left. Note * that if there are elements equal to pivot, left points to the * first slot after them -- that's why this sort is stable. * Slide elements over to make room for pivot. */ int n = start - left; // The number of elements to move // Switch is just an optimization for arraycopy in default case switch (n) { case 2: a[left + 2] = a[left + 1]; case 1: a[left + 1] = a[left]; break; default: System.arraycopy(a, left, a, left + 1, n); } a[left] = pivot; } }
)