zoukankan      html  css  js  c++  java
  • 策略模式(strategy pattern)

     

    策略模式在java集合中的TreeSet和TreeMap中得到了很好的应用,我们可以实现Comparator接口实现Compareto()方法来定义自己的排序规则,然后通过TreeSet,TreeMap构造方法传入实现该接口的实例,map中的顺序就会是我们自定义的顺序。我们可以完全定义自己的规则,用之极为方便。那么,什么是策略模式呢?

     

    策略模式定义:定义一组算法,将每个算法都封装起来,并且使它们之间可以转换。策略模式使这些算法在客户端调用时能够互不影响的变化。

     

    策略模式组成:

            1.抽象的策略角色:策略类,通常由一个抽象类或者接口实现。

            2.具体的策略角色:包装了相关的算法和行为。

            3.环境角色:持有一个策略类的引用,以便最终给客户端调用。

    策略模式的设计原则:

           1. 封装变化

           2.使用接口编程

     

    策略模式的实现:

           1.将每一组算法封装到具有共同接口的独立类中,这样不同的策略可以相互替换

               2.算法可以在不影响客户端的情况下发生变化,把行为和环境分开。

             3.环境类负责维持和查询行为类,各种算法在具体策略中提供

     

    看文字看蒙了,举一个具体的例子吧,举什么例子呢?想到我们数据结构中的各种排序,什么冒泡排序,快速排序,堆排序...,他们完成的功能都是一样的,只是排序算法不同而已。我们就可以看成是排序的不同策略。

     

    首先定义我们的抽象策略:

    /**
     * 抽象的策略类
     * @author
     *
     */
    public interface Strategy {
        
        public void sort(int[] array);
    }
    View Code

    定义具体的策略,这里实现了三种策略,分别是快速排序,堆排序,归并排序。

    快速排序策略代码:

    public class QuickSort implements Strategy{
    
        @Override
        public void sort(int[] array) {
            qpSort(array,0,array.length - 1);
        }
        
        private void qpSort(int array[], int low, int high) {
            int pos = qkPass(array, low, high); //产生中间第一个确定的数
    
            if (low < high) {
                qpSort(array, low, pos - 1);//左边
                qpSort(array, pos + 1, high);//右边
            }
        }
    
        private  int qkPass(int a[], int low, int high) {
            int x = a[low]; 
    
            while (low < high) {
    
                while (low < high && a[high] > x) {
                    high--;
                }
                if (low < high) {
                    a[low] = a[high];
                    low++;
                }
                while (low < high && a[low] < x) {
                    low++;
                }
                if (low < high) {
                    a[high] = a[low];
                    high--;
                }
            }
            a[low] = x;
    
            return low;
        }
        
    }
    View Code

     

    堆排序策略代码:

    public class HeapSort implements Strategy {
    
        @Override
        public void sort(int[] array) {
            heapSort(array,array.length);
        }
    
        private void heapSort(int a[], int length) {
    
            crtHeap(a, length); // 创建大根堆
    
            for (int i = length - 1; i > 0; i--) {
    
                int b = a[0];
    
                a[0] = a[i]; // 堆顶跟堆尾互换
    
                a[i] = b;
    
                sift(a, 0, i - 1); // 使得r[0...i-1]变成堆
            }
        }
    
        /**
         * 建立初堆
         * 
         * @param a
         *            为带排序的数组
         * @param length
         *            为数组长度
         */
        private void crtHeap(int a[], int length) {
    
            int n = length - 1;
    
            // 建出堆,从第 n/2 个记录开始进行堆筛选
            for (int i = n / 2; i >= 0; i--) {
    
                sift(a, i, n);
            }
        }
    
        /**
         * 
         * @param r
         *            数组
         * @param k
         *            表示以r[k]为根的完全二叉树,调整r[k],使得r[k...m]满足大根堆的性质
         * @param m
         *            堆尾元素下标
         */
        private void sift(int r[], int k, int m) {
    
            int temp = r[k]; // 暂存根记录
    
            int i = k; // 记录初始根的下标
    
            int j = i * 2 + 1; // 根的左孩子,因为下标从0开始
    
            while (j <= m) {
                // 如果存在右子树,且右子树根的关键字大,则沿右分支筛选,否则沿左分支筛选。因为目的是找一个最大的元素
                if (j < m && r[j] < r[j + 1]) {
                    j = j + 1;
                }
    
                if (temp >= r[j]) {
                    break; // 结束筛选
                }
                else {
                    r[i] = r[j]; // 上移
                    i = j; // 从新定义根下标
                    j = j * 2 + 1;// 继续筛选
                }
            }
    
            r[i] = temp; // 将r[k]移动到适当的位置
        }
    
    }
    View Code

     

    归并排序策略代码:

    public class MergeSort implements Strategy{
    
        @Override
        public void sort(int[] array) {
            int[] temp = new int[array.length];
            mSort(array,0,array.length - 1, temp);
        }
        
        /**
         * 
         * @param r1 等待排序数组
         * @param low 
         * @param high
         * @param r3  将r1排序后的结果放在r3中 r1[low...high],r3[low...high]
         */
        private void mSort(int r1[],int low,int high, int r3[]){
            
            
            
            if(low  < high)
            {
                int mid = (low + high) /2;
                
                //归并排序中 拆,合要一起进行
                mSort(r1,low,mid,r3);
                
                mSort(r1,mid+1,high,r3);
                
                merge(r1,low, mid, high, r3);
            }
            
        }
        
        private void merge(int r1[],int low, int mid, int high, int r2[]){
            
            int i = low;
            int j = mid + 1;
            int k = 0;
            
            while(i <=mid && j <= high){
                
                if(r1[i] <= r1[j]){
                    r2[k] = r1[i];
                    i++;
                }
                else{
                    r2[k] = r1[j];
                    j++;
                }
                
                k++;
            }
            
            while(i <= mid){
                r2[k] = r1[i];
                i++;
                k++;
            }
            
            while(j <= high){
                r2[k] = r1[j];
                j++;
                k++;
            }
            
            for(int m = 0; m < k;m++){
                r1[low + m] = r2[m];
            }
        }
    
    }
    View Code

     

    定义环境类:

    public class Environment {
        
        private Strategy strategy; //策略类的引用
        
        public Environment(Strategy strategy){
            this.strategy = strategy;
        }
        
        //用于设置不同的策略
        public void setStrategy(Strategy strategy){
            this.strategy = strategy;
        }
        
        //实现排序的功能
        public void sort(int array[]){
            strategy.sort(array);
        }
        
    }
    View Code

     

    最后定义客户端类:

    public class Client {
        
        public static void main(String[] args) {
            
            int[] array1 = new int[]{48,62,35,77,55,14,35,98};
            int[] array2 = new int[]{48,62,35,77,55,14,35,98};
            int[] array3 = new int[]{48,62,35,77,55,14,35,98};
            
            
            //使用堆排序策略
            Environment env = new Environment(new HeapSort());
            
            env.sort(array1);
            System.out.println("使用堆排序array1:");
            print(array1);
            
            //使用快速排序策略
            env.setStrategy(new QuickSort());
            env.sort(array2);
            System.out.println("使用快速排序array2:");
            print(array2);
            
            //使用归并排序策略
            env.setStrategy(new MergeSort());
            env.sort(array3);
            System.out.println("使用归并排序array3:");
            print(array3);
            
        }
        
        static void print(int[] array){
            for(int i = 0; i < array.length; i++){
                System.out.print(array[i] + "	");
            }
            System.out.println();
            System.out.println("---------------------------------");
        }
    }
    View Code

     

    运行结果如下所示:

    我们使用不同的排序策略分别对三个数组排序的功能已经实现了,程序非常灵活,我们想用什么策略来实现排序可以自己决定(通过environment.serStrategy(XXX)方法)。

    程序中Environment类根本不知道也不用管排序到底是怎么实现的,它只是持有一个具体策略类的引用,然后调用具体策略类的方法。

     

    策略模式用着很方便,但是本身也有缺点:

        1.客户端必须知道所有的策略类,并自行决定使用哪种策略类。

             2.造成很多的策略类,每一个不同的策略都需要一个策略类来实现。

     

    对于第一点很明显,我们客户端(client类)在使用策略时必须知道具体的策略类是什么,environment.serStrategy(XXX)方法也需要知道。

    对于第二点,定义了3中策略,就有3个策略类,如果策略很多的话,类也会很多。

     

    参考资料:圣思园教学视频

     

  • 相关阅读:
    REST
    Bootstrap
    深入浅出聊聊企业级API网关
    Message Queue
    pyspark
    贝叶斯解读
    Leetcode#95 Unique Binary Search Trees II
    Leetcode#24 Swap Nodes in Pairs
    Leetcode#147 Insertion Sort List
    Leetcode#98 Validate Binary Search Tree
  • 原文地址:https://www.cnblogs.com/xxez-d/p/4676248.html
Copyright © 2011-2022 走看看