定义:定义了算法家族,分别封装起来,让他们之间可以相互替换
类型:行为类模式
类图:
策略模式的结构
- 封装类:也叫上下文,对策略进行二次封装,目的是避免高层模块对策略的直接调用。
- 抽象策略:通常情况下为一个接口,当各个实现类中存在着重复的逻辑时,则使用抽象类来封装这部分公共的代码,此时,策略模式看上去更像是模版方法模式。
- 具体策略:具体策略角色通常由一组封装了算法的类来担任,这些类之间可以根据需要自由替换。
抽象策略类:
public abstract class ISortService { public abstract void sort(int[] arr); public void swap(int [] arr, int l,int r){ int temp = arr[l]; arr[l] = arr[r]; arr[r] = temp; } public void show(int[] arr){ System.out.println(Arrays.toString(arr)); } }
具体策略类:
冒泡排序:
public class BubbleSort extends ISortService{ @Override public void sort(int[] arr) { for(int i= arr.length-1;i>0;i--){ for(int j=0;j<i;j++){ if(arr[j] > arr[j+1]){ swap(arr,j,j+1); } } } } public static void main(String[] args) { int[] arr = {2,4,1,6,3,8,7,9,5}; ISortService bubbleSort = new BubbleSort(); bubbleSort.show(arr); bubbleSort.sort(arr); bubbleSort.show(arr); } }
插入排序
public class InsertSort extends ISortService { @Override public void sort(int[] arr) { for(int i=1;i<arr.length;i++){ int temp = arr[i]; int cursor = i; while (cursor > 0 && arr[cursor-1] > temp){ arr[cursor] = arr[cursor-1]; cursor --; } arr[cursor] = temp; } } public static void main(String[] args) { int[] arr = {2,4,1,6,3,8,7,9,5}; ISortService sort = new InsertSort(); sort.show(arr); sort.sort(arr); sort.show(arr); } }
选择排序
public class SelectSort extends ISortService { @Override public void sort(int[] arr) { for (int i=0;i<arr.length;i++){ int min = arr[i]; int mPos = i; for (int j=i+1;j<arr.length;j++){ if(arr[j] < min){ min = arr[j]; mPos = j; } } swap(arr,i,mPos); } } public static void main(String[] args) { int[] arr = {2,4,1,6,3,8,7,9,5}; ISortService sort = new SelectSort(); sort.show(arr); sort.sort(arr); sort.show(arr); } }
归并排序:
public class MergSort extends ISortService{ public void reMergSort(int [] arr,int l,int r){ if(l == r){ return; } int mid = (l+r)/2; reMergSort(arr,l,mid); reMergSort(arr,mid+1,r); merg(arr,l,mid,r); } public static void merg(int[] arr,int l,int m,int r){ int [] temp = new int[r-l+1]; int currentL = l,currentM = m+1; int k=0; while (currentL <= m && currentM<= r){ if(arr[currentL] < arr[currentM]){ temp[k++] = arr[currentL++]; }else { temp[k++] = arr[currentM++]; } } while (currentL <= m){ temp[k++] = arr[currentL++]; } while (currentM <= r){ temp[k++] = arr[currentM++]; } for(k=0;k<temp.length;k++){ arr[l++] = temp[k]; } } @Override public void sort(int[] arr) { reMergSort(arr,0,arr.length-1); } public static void main(String[] args) { int[] arr = {2,4,1,6,3,8,7,9,5}; ISortService sort = new MergSort(); sort.show(arr); sort.sort(arr); sort.show(arr); } }
封装类:
public class SortUtil { ISortService sort; public ISortService getSort() { return sort; } public void setSort(ISortService sort) { this.sort = sort; } public void sort(int[] arr){ sort.sort(arr); } public void show(int[] arr){ sort.show(arr); } }
测试类:
public class Client { public static void main(String[] args) throws Exception { int[] arr = getArr(150); saveToFile(arr,"old1.txt"); List<ISortService> list = new ArrayList<>(); list.add(new BubbleSort()); list.add(new InsertSort()); list.add(new SelectSort()); list.add(new MergSort()); long start, end; SortUtil sortUtil = new SortUtil(); for (int i = 0; i < 4; i++) { int[] newArr = Arrays.copyOf(arr, arr.length); sortUtil.setSort(list.get(i)); String fileName = list.get(i).getClass().getName(); // sortUtil.show(newArr); start = System.currentTimeMillis(); sortUtil.sort(newArr); end = System.currentTimeMillis(); saveToFile(newArr,fileName+".txt"); System.out.println( fileName+ "耗时: " + (end - start)); // sortUtil.show(newArr); System.out.println("------------------------"); } } public static int[] getArr(int size) { int[] arr = new int[size]; for (int i = 0; i < size; i++) { arr[i] = (int) (Math.random() * size); } return arr; } public static void saveToFile(int[] arr, String fileName) throws Exception { File file = new File("D://test/" + fileName); BufferedWriter bw = new BufferedWriter(new FileWriter(file)); int i = 1; for (int num : arr) { if (i % 16 == 0) { bw.newLine(); i = 1; } bw.write(num + "\t"); i++; } bw.flush(); bw.close(); } }
策略模式的优缺点
策略模式的主要优点有:
- 由于策略类实现自同一个抽象,所以他们之间可以自由切换。
- 易于扩展,增加一个新的策略,可以在不修改原来代码上进行扩展。
- 避免使用多重条件,如果不使用策略模式,对于所有的算法,必须使用条件语句进行连接,通过条件判断来决定使用哪一种算法
策略模式的缺点主要有两个:
- 维护各个策略类会给开发带来额外开销,可能大家在这方面都有经验:一般来说,策略类的数量超过5个,就比较令人头疼了。
- 必须对客户端(调用者)暴露所有的策略类,因为使用哪种策略是由客户端来决定的,因此,客户端应该知道有什么策略,并且了解各种策略之间的区别,否则,后果很严重。
参考:
http://blog.youkuaiyun.com/zhengzhb/article/details/7609670