美文网首页
设计模式 - 策略模式

设计模式 - 策略模式

作者: FX_SKY | 来源:发表于2017-04-26 23:15 被阅读15次

    模式定义

    定义一系列算法,将它们一个个封装起来,并且使他们之间可以相互替换。本模式使得算法可以独立于使用它的客户而变化。

    策略模式是对算法的封装,把一系列的算法分别封装到对应的类中,并且这些类实现相同的接口,相互之间可以替换。在前面说过的行为类模式中,有一种模式也是关注对算法的封装——模版方法模式,对照类图可以看到,策略模式与模版方法模式的区别仅仅是多了一个单独的封装类Context,它与模版方法模式的区别在于:在模版方法模式中,调用算法的主体在抽象的父类中,而在策略模式中,调用算法的主体则是封装到了封装类Context中,抽象策略Strategy一般是一个接口,目的只是为了定义规范,里面一般不包含逻辑。

    模式结构

    Strategy.jpg
    • 环境类(Context):也叫上下文,对策略进行二次封装,目的是避免高层模块对策略的直接调用。
    • 抽象策略(Strategy):通常情况下为一个接口,当各个实现类中存在着重复的逻辑时,则使用抽象类来封装这部分公共的代码,此时,策略模式看上去更像是模版方法模式。
    • 具体策略(ConcreteStrategy):具体策略角色通常由一组封装了算法的类来担任,这些类之间可以根据需要自由替换。

    代码实现

    public class Context {
        private Strategy strategy;
    
        public void setStrategy(Strategy strategy){
            this.strategy = strategy;
        }
    
        public void algorithm(){
            strategy.algorithm();
        }
    }
    

    抽象策略类Strategy :

    public interface Strategy {
        void algorithm();
    }
    

    具体策略实现:

    public class ConcreteStrategyA implements Strategy {
    
        @Override
        public void algorithm() {
            System.out.println("具体策略1");
        }
    }
    
    
    public class ConcreteStrategyB implements Strategy {
    
        @Override
        public void algorithm() {
            System.out.println("具体策略2");
        }
    }
    

    Client:

            Context context = new Context();
            System.out.println("-----执行策略1-----");
            context.setStrategy(new ConcreteStrategyA());
            context.algorithm();
    
            System.out.println("-----执行策略2-----");
            context.setStrategy(new ConcreteStrategyA());
            context.algorithm();
    

    排序算法

    排序策略接口:

    public interface Sort {
    
        void sort(int[] arr, int start, int end);
    }
    

    冒泡排序:

    public class BubbleSort implements Sort {
    
        @Override
        public void sort(int[] arr, int start, int end) {
            System.out.println("冒泡排序实现");
            for(int i=start; i<end; i++){
                for(int j = start; j<arr.length-i-1; j++){
                    //这里-i主要是每遍历一次都把最大的i个数沉到最底下去了,没有必要再替换了
                    if(arr[j]>arr[j+1]){
                        int temp = arr[j];
                        arr[j] = arr[j+1];
                        arr[j+1] = temp;
                    }
                }
            }
        }
    }
    

    快速排序:

    public class QuickSort implements Sort {
    
        @Override
        public void sort(int[] arr, int start, int end) {
            System.out.println("快速排序实现");
            quickSort(arr, start, end-1);
        }
    
        private void quickSort(int[] numbers, int start, int end) {
            if (start < end) {
                int base = numbers[start]; // 选定的基准值(第一个数值作为基准值)
                int temp; // 记录临时中间值
                int i = start, j = end;
                do {
                    while ((numbers[i] < base) && (i < end))
                        i++;
                    while ((numbers[j] > base) && (j > start))
                        j--;
                    if (i <= j) {
                        temp = numbers[i];
                        numbers[i] = numbers[j];
                        numbers[j] = temp;
                        i++;
                        j--;
                    }
                } while (i <= j);
                if (start < j)
                    quickSort(numbers, start, j);
                if (end > i)
                    quickSort(numbers, i, end);
            }
        }
    }
    

    上下文环境:

    public class Context {
        private Sort strategy;
    
        public void setStrategy(Sort strategy){
            this.strategy = strategy;
        }
    
        public void sort(int[] arr, int start, int end) {
            strategy.sort(arr, start, end);
        }
    }
    

    客户端:

    public class SortClient {
    
        public static void main(String[] args) {
    
            int[] arr = {10, 1, 8, 6, 5, 3, 2};
    
            Context context = new Context();
            System.out.println("-----执行冒泡排序-----");
            context.setStrategy(new BubbleSort());
            context.sort(arr, 0, arr.length);
    
            System.out.println("-----执行快速排序-----");
            context.setStrategy(new QuickSort());
            context.sort(arr, 0, arr.length);
        }
    }
    

    优缺点

    优点

    策略模式的优点:

    • 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
    • 策略模式提供了可以替换继承关系的办法。
    • 使用策略模式可以避免使用多重条件转移语句。

    缺点

    • 客户必须了解不同的Strategy
    • 策略模式将造成产生很多策略类

    源码下载

    https://github.com/TiFG/design-patterns/tree/master/strategy

    相关文章

      网友评论

          本文标题:设计模式 - 策略模式

          本文链接:https://www.haomeiwen.com/subject/ghowzttx.html