java 设计模式之Strategy(策略模式)

策略模式

策略模式的定义

策略模式(Strategy Pattern) 是一种比较简单的模式,也叫做政策模式(Policy Pattern)其定义如下:
Define a family of algorithms,encapsulate each one,and make them interchangeable.(定义一组 算法,将每个算法都封装起来,并且使它们之间可以互换。)ps:摘取《设计模式之禅》
这个定义非常明确,清晰的。“定义一组算法”。简单来说就是一个方法可以有多种方式来实现他,定义多种策略。

代码实现

举个例子:

import java.io.*;
class StrategyTest  
{
   //定义排序算法
   public static void compareTo(int[] arr){
   //对传进来的数组进行遍历
       for(int i=0;i<arr.length-1;i++){
       	//	创建一个比较大小的值
           int minPos=i;
           //在第一个循环的基础上取出index后面的值来与之比较
           for(int j=i+1;j<arr.length;j++){
           	//将最大的值的index下标取出来
                 minPos=arr[j]<arr[minPos]?j:minPos;
           }
           //进行交换
           swapto(i,minPos,arr);
       }
   }
   public static void swapto(int i,int j,int[] arr){
       int cont=arr[i];
       arr[i]=arr[j];
       arr[j]=cont;
   }
   public static void main (String[] args) throws java.lang.Exception
   {
   	int[] arr=new int[]{5,9,1,2};
   	StrategyTest.compareTo(arr);
   	for(int i:arr){
   	  System.out.println(i); 
   	}
   }
}

上面是一个简单的排序算法,但是现在它的可扩展性不强,只有一个int类型的比较,假如我想要其他的类型的排序的话怎么办呢?
可以自定义一个接口来定义算法

import java.io.*;
class StrategyTest  implements Comparator<StrategyTest>
{
   //创建一个构造方法
   public StrategyTest(int width){
       this.width=width;
   }
   //定义一个比较的变量,这里写的不是很严谨,没有定义为私有变量,没有生成get/set方法,因为这台电脑没有idea,是在在线编辑器敲的,所有代码看起来比较乱
    int width;
    //这是实现接口的具体方法,由这个方法来定义算法的实现方式
   public int comparableTo(StrategyTest o2){
       //将两个类的width属性进行比较
       if(this.width<o2.width)return 1;
       else if (this.width>o2.width) return -1;
       else return 0;
   }
   //这个是排序算法
   public static void compareTo(StrategyTest[] arr){
       for(int i=0;i<arr.length-1;i++){
           int minPos=i;
           for(int j=i+1;j<arr.length;j++){
           	//将width属性的最大值比较出来
                 minPos=(arr[j].compare(arr[minPos])==-1)?j:minPos;
           }
           //调用交换方法
           swapto(i,minPos,arr);
           
       }
   }
   public static void swapto(int i,int j,StrategyTest[] arr){
       StrategyTest cont=arr[i];
       arr[i]=arr[j];
       arr[j]=cont;
   }
//最好在生成一个toString方法!!!
   public static void main (String[] args) throws java.lang.Exception
   {
   	
   	StrategyTest[] arr=new StrategyTest[]{new StrategyTest(5),new StrategyTest(9),new StrategyTest(1)};
   	StrategyTest.compareTo(arr);
   	for(StrategyTest i:arr){
   	  System.out.println(i.width); 
   	}
   	
   	
   }
}
//定义一个接口,接口中有一个泛型方法,可由这个方法来自定义你所需要的排序算法
interface Comparable<T>{
   int comparableTo(T o2);
}

以上是我自己定义了一个Comparator接口,java内部jdk中也有这样的一个方法,在java.util包中。java内部封装好了的。
虽然这个方法可以满足对象的封装比较算法,但是还是存在缺点,比如我现在还要一个比较高的对象算法,改怎么扩展呢?重新在写一个类?显然不太现实。
终于进入今天的主题了 《策略模式》
策略模式使用的就是面向对象的继承和多态机制,非常容易理解和掌握。我们再来看策略模式的三个角色。
1.Context角色:起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。
2.Strategy抽象策略角色:策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。
3.ConcreteStrategy具体策略角色:实现抽象策略中的操作,该类含有具体的算法。

问题:现在我既先要用排序算法又想用冒泡算法。那么我应该怎么在策略模式中体现呢?

话不多说!上代码

package com.fh.util.strategy;

/**
 * 排序策略接口
 * @author Xuzs
 */
public interface SortStrategy {
    /**
     * 定义一个排序接口
     */
    public void sortStrategy(int[] arr);
}

package com.fh.util.strategy;

/**
 * 选择排序算法
 * @author Xuzs
 */
public class SelectSortStrategy implements SortStrategy{
    @Override
    public void sortStrategy(int[] arr) {
        for (int i=0;i<arr.length;i++){
            int temp=i;
            for (int j=0;j<arr.length-1;j++){
                temp=arr[temp]<arr[j]?temp:j;
                stwp(i,temp,arr);
            }
        }
    }
    public void stwp(int i,int j,int[] arr){
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }

}

package com.fh.util.strategy;

/**
 * 冒泡排序算法策略
 * @author Xuzs
 */
public class BubblingSortStrategy implements SortStrategy{
    /**
     * 实现具体的排序算法
     * @param arr
     */
    @Override
    public void sortStrategy(int[] arr) {
        for (int j=0;j<arr.length;j++){
            for(int i=0;i<arr.length-1-j;i++){
                if(arr[i]<arr[i+1]){
                    int temp=arr[i];
                    arr[i]=arr[i+1];
                    arr[i+1]=temp;
                }
            }
        }
    }
}

package com.fh.util.strategy;

import freemarker.template.utility.Execute;

/**
 * 策略执行者
 * @author Xuzs
 */
public class ExecuteStrategy {
    private SortStrategy sortStrategy;
   public ExecuteStrategy(SortStrategy sortStrategy){
        this.sortStrategy=sortStrategy;
    }
    public void execute(int[] arr){
       this.sortStrategy.sortStrategy (arr);
    }
}

package com.fh.util.strategy;

public class Test1 {
    public static void main(String[] args) {
        int[] arr=new int[]{5,8,1,3};
        ExecuteStrategy executeStrategy=new ExecuteStrategy (new BubblingSortStrategy ());
        executeStrategy.execute (arr);
        for (int i:arr){
            System.out.println (i);
        }
    }
}

策略模式的应用

1.策略模式的优点

	算法可以自由切换。
	避免使用多重条件判断。
	扩展性良好

2.策略模式的缺点

	 策略类数量增多,每一个策略对应一个类,复用的可能性比较小,类数量增多。后期维护造成一定难度
	 所有的策略类都需要对外暴露。上层模块必须知道有哪些策略,然后才能决定用那一种策略。这与迪米特法则是相违背的,我只是想使用一个策略,我凭什么就要了解这个策略呢?那要你的封装类还有什么意义?这是原装策略模式的一个缺点,幸运的是,我们可以使用其他模式来修正这个缺陷,如果工厂方法模式、代理模式或享元模式。

3. 策略模式的应用场景

	多个类只有在算法或行为上稍有不同的场景。
	算法需要自由切换的场景。
	需要屏蔽算法规则的场景。

4.策略模式需要注意的事项

如果系统中的一个策略家族的具体策略数量超过4个,则需要考虑使用混合模式,解决策略类膨胀和对外暴露的问题,否则日后的系统维护就会变成一个烫手山芋。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值