淺析設計模式中的策略模式,包含原理解讀和具體案例代碼的實現。僅為個人學習總結分享,希望圍觀者多提意見。 ...
1、概述
在開發過程中常常會遇到類似問題,實現一個功能的時候往往有多種演算法/方法(策略),我們可以根據環境的不同來使用不同的演算法或策略來實現這一功能。 如在人物比較排序的實現中,我們有時需要把年齡做為比較的標準,或者有時又想將身高作為比較的標準,不同的比較標準也就衍生出了統一個比較目的的不同演算法實現,在搜索問題中也是類似,有可能用到二分查找、順序查找之類。通常較簡單直接的思維便是將所有的演算法(策略)寫成一個類的方法,再通過客戶端去調用;也可一將所有的演算法全部封裝在一個方法中用一堆的if...else...語句來判斷。如果需要增加一種演算法時,就需要去修改封裝演算法類的源代碼;更換比較排序演算法時,又需要去修改客戶端代碼。在演算法類中封裝了大量的演算法,該類代碼較複雜,維護困難;而且將策略包含在客戶端,將導致客戶端的程式龐大難以維護。 案例:出行旅游:出行旅游時,我們有以下幾個策略可供選擇:自行車、汽車、火車、飛機等,不同的方式,單都是去實現旅行這一個目的,選擇策略的依據是時間、金錢、方便程度(對應到工程中就是需求的環境)。2、目的
策略模式的目的在於:使演算法和對象分離開來,能讓演算法獨立於對象去變化。 核心思想其實是利用了面向對象編程多態的使用。3、適用場景
當存在一下情況時使用Strategy模式: 1)許多類實現統一目的,僅方式不同。“策略”提供了一種用多個行為中的一種來配置類的實現的方法,及一個系統可以動態的在多個演算法中選擇其中一種; 2)需要同一中演算法的不同變體。如:在比較對象時,採用的比較演算法的不同,有可能需要去比較對象的成員變數; 3)一個類或者方法中定義了多種行為,並且這些行為以多個判斷語句來相互切換。可將相關的條件分支移入各自的Strategy類中去實現。 4)演算法的封裝。通過策略模式向使用演算法的客戶隱藏演算法的具體實現。4、結構與組成
策略模式的結構主要分類三個部分: 抽象策略類(Strategy):定義所有實現演算法的公共介面,Context直接使用介面調用ConcreteStrategy的具體演算法。 具體策略類(ConcreteStrategy):實現具體的演算法,每個具體的演算法類必須實現Strategy介面。 環境類(Context):具體演算法的使用類,需要用指定的一個ConcreteStrategy來配置。
4、實現
一個班級的若幹個學生,對他們進行排序分別按照名字、年齡、id排序(正序和倒序兩種方式),如年齡和名字重覆,則使用id進行升序排序。1 package com.cnblogs.vicentzh.strategymodel; 2 3 import java.util.ArrayList; 4 import java.util.Collections; 5 import java.util.Comparator; 6 import java.util.Iterator; 7 import java.util.List; 8 9 public class StrategyModel 10 { 11 /** 12 * @Describe 客戶端程式 13 * @param args 14 */ 15 public static void main(String[] args) 16 { 17 Student p1 = new Student("Tom",1,20); 18 Student p2 = new Student("Tonny",2,50); 19 Student p3 = new Student("Tom",5,30); 20 Student p4 = new Student("John",8,10); 21 Student p5 = new Student("Susan",9,15); 22 23 List<Student> students = new ArrayList<Student>(); 24 students.add(p1); 25 students.add(p2); 26 students.add(p3); 27 students.add(p4); 28 students.add(p5); 29 30 Context env = new Context(); 31 32 //正序排列 33 UpNameSort uns = new UpNameSort(); 34 env.setSortStrategy(uns); 35 env.sort(students); 36 37 for (Iterator<Student> iter=students.iterator(); iter.hasNext();) 38 { 39 Student student = iter.next(); 40 System.out.println("id: " + student.getId() + ", name: " + student.getName() 41 + ", age:" + student.getAge()); 42 } 43 System.out.println("-----------------------"); 44 45 //倒序排列 46 DownNameSort dns = new DownNameSort(); 47 env.setSortStrategy(dns); 48 env.sort(students); 49 50 for (Iterator<Student> iter=students.iterator(); iter.hasNext();) 51 { 52 Student student = iter.next(); 53 System.out.println("id: " + student.getId() + ", name: " + student.getName() 54 + ", age:" + student.getAge()); 55 } 56 57 } 58 } 59 60 61 //需要用到的具體實例類 62 class Student 63 { 64 private String name; 65 private int age; 66 private int id; 67 68 public Student(String name, int age, int id) 69 { 70 this.name = name; 71 this.age = age; 72 this.id = id; 73 } 74 75 public String getName() 76 { 77 return name; 78 } 79 public int getAge() 80 { 81 return age; 82 } 83 public int getId() 84 { 85 return id; 86 } 87 } 88 89 90 //抽象策略類(Strategy),即策略介面 91 interface SortStrategy 92 { 93 public void sortStudent(List<Student> students); 94 } 95 96 97 //具體策略類(ConcreteStrategy),即具體正序演算法實現類 98 class UpNameSort implements SortStrategy,Comparator<Student> 99 { 100 @Override 101 public void sortStudent(List<Student> students) 102 { 103 Collections.sort(students, this); 104 } 105 106 @Override 107 public int compare(Student o1, Student o2) 108 { 109 int result = o1.getName().compareTo(o2.getName()); 110 if(0==result) 111 { 112 return o1.getId() - o2.getId(); 113 } 114 return result; 115 } 116 } 117 118 //具體策略類(ConcreteStrategy),即具體倒序演算法實現類 119 class DownNameSort implements SortStrategy, Comparator<Student> 120 { 121 @Override 122 public void sortStudent(List<Student> students) 123 { 124 Collections.sort(students, this); 125 126 } 127 128 @Override 129 public int compare(Student o1, Student o2) 130 { 131 int result = o2.getName().compareTo(o1.getName()); 132 if(0==result) 133 { 134 return o1.getId() - o2.getId(); 135 } 136 return result; 137 } 138 } 139 140 //使用環境類(Context) 141 //環境類根據接收到客戶端具體的策略來對對象進行使用,同樣也能用setSortStrategy方法 142 //隨時根據客戶端的需求去改變策略演算法,並且不影響對象。 143 class Context 144 { 145 private SortStrategy concreteStrategy; //使用策略配置環境類 146 147 public Context(SortStrategy conSortStrategy) 148 { 149 this.concreteStrategy = conSortStrategy; 150 } 151 152 public Context() 153 { 154 155 } 156 157 //可隨意定製化具體策略 158 public void setSortStrategy(SortStrategy conSortStrategy) 159 { 160 this.concreteStrategy = conSortStrategy; 161 } 162 163 //使用具體的策略(concreteStrategy)對對象進行操作 164 public void sort(List<Student> students) 165 { 166 concreteStrategy.sortStudent(students); 167 } 168 }View Code