設計模式之策略模式

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;
        }
    }

 

相關文章
相關標籤/搜索