java设计模式--策略模式
策略模式(Strategy)
策略模式(Strategy Pattern)中体现了两个非常基本的面向对象设计的原则:
a.封装变化的概念
b.编程中使用接口,而不是对接口的实现
策略模式的定义:
a.定义一组算法,将每个算法都封装起来,并且使它们直接可以互换。
b.策略模式使这些算法在客户端调用它们的时候能够互不影响地变化。
策略模式的意义:
a.策略模式使开发人员能够开发出由许多可替换的部分组成的软件,并且各个部分之间是弱连接的关系
b.弱连接的特性使软件具有更强的可扩展性,易于维护,更重要的是,它大大提高了软件的可重用性.
策略模式的组成:
-抽象策略角色:策略类,通常由一个接口或者抽象类实现
-具体策略角色:包装了相关的算法和行为
-环境角色:持有一个策略类的引用,最终给客户端调用的
策略模式的实现:
-策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立类中,从而
使得它们可以相互替换。
-策略模式使得算法可以在不影响到客户端的情况下发生变化。使用策略模式可以把行为和环境分割开来。
-环境类负责维持和查询行为类,各种算法则在具体策略中提供。由于算法和环境独立开发,算法的修改都不会
影响环境和客户端
策略模式的编写步骤:
1.对策略对象定义一个公共接口
2.编写策略类,该类实现了上面的公共接口
3.在使用策略对象的环境类中保存一个对策略对象的引用
4.在使用策略对象的类中,实现对策略对象的set和get方法(注入)或者使用构造方法完成赋值。
策略模式的缺点:
1.客户端必须知道所有的策略类,并自行决定使用哪一个策略类
2.造成很多的策略类
针对策略模式的缺点,看看方案:
采用工厂模式
举例1:
实现两个数字的加,减,乘,除功能
先定义一个公共接口: public interface Strategy { public int calculate(int a,int b); } 编写策略类: 加法策略类: public class AddStrategy implements Strategy { @Override public int calculate(int a, int b) { return a + b; } } 减法策略类: public class SubtractStratagy implements Strategy { @Override public int calculate(int a, int b) { return a - b; } } 乘法策略类: public class MultiplyStrategy implements Strategy { @Override public int calculate(int a, int b) { return a * b; } } 除法策略类: public class DivideStrategy implements Strategy { @Override public int calculate(int a, int b) { return a / b; } } 创建一个环境类: public class Environment { private Strategy strategy; public Environment(Strategy strategy) { this.strategy = strategy; } public void setStrategy(Strategy strategy) { this.strategy = strategy; } public int calculate(int a,int b) { return strategy.calculate(a, b); } } 创建一个测试类: public class Client { public static void main(String[] args) { AddStrategy add = new AddStrategy(); SubtractStratagy sub = new SubtractStratagy(); MultiplyStrategy mul = new MultiplyStrategy(); DivideStrategy div = new DivideStrategy(); Environment environment = new Environment(add); System.out.println(environment.calculate(2, 5)); environment.setStrategy(sub); System.out.println(environment.calculate(2, 5)); environment.setStrategy(mul); System.out.println(environment.calculate(2, 5)); environment.setStrategy(div); System.out.println(environment.calculate(2, 5)); } } 到此第一个策略模式的案例就完成了
举例2:
对数组类的数字进行排序,有冒泡排序,快速排序,折半排序
编写接口: public interface SortStrategy { public int[] sort(int[] nums); } 编写策略类:冒泡排序,快速排序,折半排序 冒泡排序策略类: public class BubbleSortStrategy implements SortStrategy { /** * 功能:冒泡排序 */ @Override public int[] sort(int[] nums) { for(int i = 0;i < nums.length-1;i++) { for(int j = 0;j < nums.length-i-1;j++) { if(nums[j] > nums[j+1]) { int temp = nums[j]; nums[j] = nums[j+1]; nums[j+1] = temp; } } } return nums; } } 快速排序策略类: public class QuicklySortStrategy implements SortStrategy { @Override public int[] sort(int[] nums) { return quicklySort(nums,0,nums.length-1); } private int[] quicklySort(int[] nums,int low,int high) { if(low < high) { int povitePosition = adjust(nums,low,high); quicklySort( nums , low , povitePosition - 1); quicklySort( nums , povitePosition + 1 , high ); } return nums; } private int adjust(int[] nums,int low,int high) { int pivote = nums[low]; while(low < high) { while(high > low && compare(pivote,nums[high])<=0) { high--; } nums[low] = nums[high]; while(low < high && compare( pivote , nums[low] ) >= 0) { low++; } nums[high] = nums[low]; } nums[low] = pivote; return low; } private int compare(int num1,int num2) { return num1 - num2; } } 折半排序策略类: public class BinaryInsertSortStrategy implements SortStrategy { @Override public int[] sort(int[] nums) { return binaryInsertSort(nums); } private int[] binaryInsertSort(int[] data) { for (int i = 1; i < data.length; i++) { if (data[i] < data[i - 1]) { // 缓存i处的元素值 int tmp = data[i]; // 记录搜索范围的左边界 int low = 0; // 记录搜索范围的右边界 int high = i - 1; while (low <= high) { // 记录中间位置 int mid = (low + high) / 2; // 比较中间位置数据和i处数据大小,以缩小搜索范围 if (data[mid] < tmp) { low = mid + 1; } else { high = mid - 1; } } // 将low~i处数据整体向后移动1位 for (int j = i; j > low; j--) { data[j] = data[j - 1]; } data[low] = tmp; } } return data; } } 环境类: public class Environment { private SortStrategy sortStrategy; public Environment(SortStrategy sortStrategy) { this.sortStrategy = sortStrategy; } public int[] sort(int[] nums) { return sortStrategy.sort(nums); } public void setSortStrategy(SortStrategy sortStrategy) { this.sortStrategy = sortStrategy; } } 测试类: public class SortClient { public static void main(String[] args) { int[] data = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 }; BubbleSortStrategy bubble = new BubbleSortStrategy(); QuicklySortStrategy quick = new QuicklySortStrategy(); BinaryInsertSortStrategy binary = new BinaryInsertSortStrategy(); Environment env = new Environment(bubble); data = env.sort(data); System.out.println("冒泡排序:"); for(int i = 0;i < data.length;i++) { System.out.print(data[i]+" "); } System.out.println(""); env.setSortStrategy(quick); data = env.sort(data); System.out.println("快速排序:"); for(int i = 0;i < data.length;i++) { System.out.print(data[i]+" "); } System.out.println(""); env.setSortStrategy(binary); data = env.sort(data); System.out.println("折半排序:"); for(int i = 0;i < data.length;i++) { System.out.print(data[i]+" "); } } } 输出结果: 冒泡排序: 1 2 3 4 5 6 7 8 9 快速排序: 1 2 3 4 5 6 7 8 9 折半排序: 1 2 3 4 5 6 7 8 9