(设计模式)策略模式-java
来源:互联网 发布:cfd流体分析软件 编辑:程序博客网 时间:2024/06/05 05:08
•策略模式,将一个一组作用类似的算法包装起来,使他们可相互替代,算法可独立于客户端变化,且增加新的算法非常容易,也称为政策模式。
•策略模式着重于算法的替代性,即根据不同的场景使用不同的算法,系统的健壮性因此提高。
•策略模式是以算法为单位,有时候容易和模板模式混在一起,模板模式一般是一个算法中的某一步不同,算法的骨架是大致固定的,而策略模式一般是算法为一个单位。且策略模式的算法都是公共的,可独立于客户端调用,而模板模式一般不能独立调用。
•策略模式的角色组成:
①上下文角色(Context):可注入一个策略对象,持有一个策略的引用。客户端通过上下文对象来调用策略。
/** * 策略的上下文:和策略打交道,可以理解为是对策略的调用, * 上下文和接口进行复杂交互。商城的调用者和上下文打交道。 * 就比如电脑维修工,客户电脑坏了,不会去店里直接找某个维修工, * 客户只会在网上查找相关的服务或者找客服姐姐,网站或客服姐姐帮你安排相应的维修工, * 这个网站或者客服姐姐就是这个上下文,和相关的维修工打交道。 * @author btp * */public class ContextUseStrategy { /* * 封装了一个策略 */ private FictitiousStrategy aStrategy; /* * 构造一个上下文对象,将策略对象传入 */ public ContextUseStrategy(FictitiousStrategy aStrategy){ this.aStrategy = aStrategy; } /* * 调用策略 */ public void executeStrategy(){ this.aStrategy.executeStrategy(); } public FictitiousStrategy getaStrategy() { return aStrategy; } public void setaStrategy(FictitiousStrategy aStrategy) { this.aStrategy = aStrategy; }}
②抽象策略角色(Strategy):定义了一个上下文对象可调用的公共方法。
/** * 虚拟的策略:策略的父类,表明提供策略。针对一组策略。 * 准备一组算法,并将每一个算法封装起来,使得它们可以互换。 * 策略模式代表一个算法族,算法之间可以相互替代,比如: * 我们有几个电脑维修工,维修来自客户的坏电脑,每个维修工相当于一个算法, * 根据电脑的类型和电脑的损坏程序安排维修工去维修,可能有些维修工擅长维修笔记本, * 有些擅长维修台式机,或者来了一个电脑,你搞不定我再来搞定,总有一个人能搞定 * @author btp * */public abstract class FictitiousStrategy { /* * 执行策略 */ public abstract void executeStrategy();}
③具体策略角色(Concrete Strategy):实现抽象策略类的公共方法,并提供不同的可替代的实现。
/** * 具体的策略类:包含真正可以执行的算法 * 从虚拟策略类继承而来。 * 比如擅长修理笔记本的维修工A * @author btp * */public class ConcreteStrategy1 extends FictitiousStrategy{ @Override public void executeStrategy() { //算法的实现 System.out.println("算法1执行"); }}
/** * 具体的策略类:包含真正可以执行的算法 * 从虚拟策略类继承而来 * 比如擅长维修台式机的维修工B * @author btp * */public class ConcreteStrategy2 extends FictitiousStrategy{ @Override public void executeStrategy() { //算法的实现 System.out.println("算法2执行"); }}
然后上层调用者就可以调用上下文环境:
/** * 上层调用者,和上下文交互 * @author btp * */public class ContextUser { public static void main(String[] args) { //使用算法1 ContextUseStrategy context = new ContextUseStrategy(new ConcreteStrategy1()); context.executeStrategy(); //使用算法2 context.setaStrategy(new ConcreteStrategy2()); context.executeStrategy(); //使用算法3 context.setaStrategy(new FictitiousStrategy(){ @Override public void executeStrategy() { //算法的实现 System.out.println("算法3执行"); } }); context.executeStrategy(); }}
看上去就像Spring中的各种注入方式,根据不同的情况选择不同的注入方式。
•大家都知道有许多种排序方式,比如内部排序中的冒泡,插入,归并等,这些排序方式有时候也各有优缺点,比如基本有序的序列选择插入排序,数据规模较大的时候使用归并排序可能更好一点。以下就用排序算法做一个例子。
import java.lang.reflect.Array;import java.util.Arrays;//一个排序算法族public class StrategyTest { public static void main(String[] args) { //客户端 //使用冒泡排序 SortUse<Integer> user = new SortUse<Integer>(new Integer[]{99,2,100,33,2,2,3,555,6,7,88},new BubbleSort<Integer>()); System.out.println("冒泡排序前:"+user); user.sort(); System.out.println("冒泡排序后:"+user); //使用插入排序 user.setT(new Integer[]{45,2,4,111,98,54,0,1,2}); user.setSort(new InsertSort<Integer>()); System.out.println("插入排序前:"+user); user.sort(); System.out.println("插入排序后:"+user); //使用直接选择排序 user.setT(new Integer[]{45,2,4,111,98,54,0,1,2}); user.setSort(new SelectionSort<Integer>()); System.out.println("直接选择排序前:"+user); user.sort(); System.out.println("直接选择排序后:"+user); //使用归并排序 user.setT(new Integer[]{45,2,4,111,98,54,0,1,2}); user.setSort(new MergeSort<Integer>()); System.out.println("归并排序前:"+user); user.sort(); System.out.println("归并排序后:"+user); //使用归并排序 user.setT(new Integer[]{111,98,54,45,4,2,2,1,0}); user.setSort(new QuickSort<Integer>()); System.out.println("快速排序前:"+user); user.sort(); System.out.println("快速排序后:"+user); }}/* * 排序算法的上下文:持有一个排序算法的引用。和算法交互。调用排序算法。 */class SortUse<T extends Comparable<? super T>>{ private Sort<T> sort; private T[] t; //传入要排序的对象数组以及要使用的排序算法对象 public SortUse(T[] t,Sort<T> sort){ this.sort = sort; this.t = t; } public void sort(){ this.sort.sort(t); } public Sort<T> getSort() { return sort; } public void setSort(Sort<T> sort) { this.sort = sort; } public T[] getT() { return t; } public void setT(T[] t) { this.t = t; } public String toString(){ return Arrays.toString(t); }}/* *排序的虚拟类:代表一个排序算法对象。 为上下文对象定义了公共接口。 */abstract class Sort<T extends Comparable<? super T>>{ public abstract void sort(T[] t);}/* * 具体的算法实现类:实现了虚拟类的接口 * 具体的算法实现类:冒泡排序 */class BubbleSort<T extends Comparable<? super T>> extends Sort<T>{ @Override public void sort(T[] t) { T temp; for(int i = t.length-1;i>=0;i--){ for(int j = i-1;j>=0;j--){ if(t[i].compareTo(t[j]) < 0){ temp = t[i]; t[i] = t[j]; t[j] = temp; } } } }}/* * 具体的算法实现类:插入排序 * 将值插入一个已经排好序的序列 */class InsertSort<T extends Comparable<? super T>> extends Sort<T>{ @Override public void sort(T[] t) { T temp; //从第一个开始排 for(int i = 1;i < t.length;i++){ for(int j = 0;j < i;j++){ if(t[i].compareTo(t[j]) < 0){ temp = t[i]; //要插入的位置之后的元素全部向后移 for(int k = i;k > j;k--){ t[k] = t[k-1]; } t[j] = temp; break; } } } }}/* * 具体的算法实现类:直接选择排序 * 从后面的序列中选取最大或最小的值,将其和已经排好序的序列的后一位交换值 */class SelectionSort<T extends Comparable<? super T>> extends Sort<T>{ @Override public void sort(T[] t) { //记录要交换元素的坐标 int index; //记录最小值 T min; //临时值,交换两个坐标的值使用 T temp; for(int i = 0;i < t.length-1;i++){ min = t[i]; index = i; for(int j = i+1;j < t.length;j++){ if(min.compareTo(t[j]) > 0){ min = t[j]; index = j; } } temp = t[i]; t[i] = t[index]; t[index] = temp; } }}/* * 具体的算法实现类:归并排序 * (1)两个序列各自排好序 * (2)合并两个排好序的序列,使之成为一个有序的序列 */class MergeSort<T extends Comparable<? super T>> extends Sort<T>{ @Override public void sort(T[] t) { sort(t,0,t.length-1); } private void sort(T[] t,int low,int high){ int middle = (low + high) / 2; if(low < high){ //middle左边排序 sort(t,low,middle); //middle右边排序 sort(t,middle+1,high); //排好序的两个序列合并 mergeTwoList(t,low,middle,high); } } //两个排好序的数组进行合并 @SuppressWarnings("unchecked") private void mergeTwoList(T[] t,int low,int middle,int high){ if(t.length > 0 && null != t[0]){ //构建一个临时数组,存放排序后的值 T[] temp = (T[]) Array.newInstance(t[0].getClass(), high - low +1); int headOfList1 = low; int headOfList2 = middle + 1; int indexOfTemp = 0; while(headOfList1 <= middle && headOfList2 <= high){ if(t[headOfList1].compareTo(t[headOfList2]) < 0){ temp[indexOfTemp++] = t[headOfList1++]; }else{ temp[indexOfTemp++] = t[headOfList2++]; } } //此时一定有一个数组走空或两个数组走空,把另一个数组的残余数据移到临时数据中 while(headOfList1 <= middle){ temp[indexOfTemp++] = t[headOfList1++]; } while(headOfList2 <= high){ temp[indexOfTemp++] = t[headOfList2++]; } indexOfTemp = 0; //把排好序的临时数组的数据移到原先的数组中 for(int i = low;i <= high;i++){ t[i] = temp[indexOfTemp++]; } }else{ throw new RuntimeException(); } }}/* * 具体的算法实现类:快速排序 *(1)在数据集之中,选择一个元素作为"基准"(pivot)。 *(2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。 *(3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。 */class QuickSort<T extends Comparable<? super T>> extends Sort<T>{ @Override public void sort(T[] t) { sort(t,0,t.length-1); } private void sort(T[] t,int low,int high){ //low < high的情况下才排序 if(low < high){ T baseObject = t[low]; int left = low; int right = high; //记录下一个要填的坐标值 int index = low; while(left != right){ //防止空指针把left < right放到前面来 while(left < right && t[right].compareTo(baseObject) >= 0){ right--; } t[index] = t[right]; t[right] = null; index = right; while(left < right && t[left].compareTo(baseObject) <= 0){ left++; } t[index] = t[left]; t[left] = null; index = left; } t[index] = baseObject; //左半区排序 sort(t,low,index-1); //右半区排序 sort(t,index+1,high); } }}
阅读全文
1 0
- java 设计模式--策略模式(strategy)
- Java设计模式(四)策略模式
- 设计模式之策略模式(java)
- Java设计模式(一) 策略模式
- Java设计模式----策略模式(Strategy)
- java设计模式(五)--策略模式
- Java设计模式(十二) 策略模式
- java设计模式(2)策略模式
- Java设计模式( 策略模式)
- java设计模式:(策略模式)
- 设计模式之策略模式(java)
- Java设计模式(策略模式)
- (设计模式)策略模式-java
- Java设计模式(十二) 策略模式
- java设计模式(一)-策略模式
- 设计模式-策略模式(java)
- Java设计模式 -- 策略模式
- java设计模式-----策略模式
- 构建一个文本搜索系统
- Sublime Text 3 快捷键汇总
- 424. Longest Repeating Character Replacement
- 在mac上通过Homebrew安装redis
- shader之半兰伯特漫反射
- (设计模式)策略模式-java
- 第一章 初识Hadoop
- java 根据输入的时间打印本月的日历
- python中关于if name == 'main'
- mysql最新配置
- 登录后台逻辑三之session和cookie
- Linux之分段机制和分页机制
- python 验证码
- byte 与 int 转换