zoukankan      html  css  js  c++  java
  • [design pattern](1) Strategy

    引言

    最近,在学习设计模式相关的知识。本博客主要想讲一讲策略模式,这也是我学习的第一个模式。写下这篇博客,主要想记录下个人的一点理解,也是想通过写博客的方式来加深对与Strategy的一点理解。以下的内容如果有什么说的不对的地方,还请各位大神指正。

    思考题

    首先我们来思考下面的一个问题:

    问题:写出冒泡排序和快速排序算法,并且根据传参不同,使用不同的排序算法排序。

    首先,来看没有使用设计模式的代码是什么样子:

    SortAlgorithm.java:
    import java.util.Random;
    import java.util.Arrays;
    
    public class SortAlgorithm {
        private static int index = 10000;
        private static int randomMax = 50000;
        private static Integer[] oldOrder = new Integer[index];
        private static Random random = new Random();
        static {
            for(int i = 0; i < index; i++) {
                oldOrder[i] = random.nextInt(randomMax);
            }
        }
        
        //通过设置算法名称来决定用什么算法
        private String algorithmName;
        
        public static void main(String... args) {
            SortAlgorithm sortAlgorithm = new SortAlgorithm();
            Integer[] oldOrder1 = Arrays.copyOf(oldOrder, index);
            Integer[] oldOrder2 = Arrays.copyOf(oldOrder, index);
            
            sortAlgorithm.setAlgorithmName("bubble");
            //System.out.println(String.format("BubbleSort sort before order:%s", Arrays.asList(oldOrder1).toString()));
            long startTime = System.currentTimeMillis();
            Integer[] newOrder1 = sortAlgorithm.executeAlgorithm(oldOrder1);
            System.out.println(String.format("BubbleSort take time:%s", System.currentTimeMillis() - startTime));
            //System.out.println(String.format("BubbleSort sort after order:%s", Arrays.asList(newOrder1).toString()));
            
            sortAlgorithm.setAlgorithmName("quick");
            //System.out.println(String.format("QuickSort sort before order:%s", Arrays.asList(oldOrder2).toString()));
            startTime = System.currentTimeMillis();
            Integer[] newOrder2 = sortAlgorithm.executeAlgorithm(oldOrder2);
            System.out.println(String.format("QuickSort take time:%s", System.currentTimeMillis() - startTime));
            //System.out.println(String.format("QuickSort sort after order:%s", Arrays.asList(newOrder2).toString()));
        }
        
        public Integer[] executeAlgorithm(Integer[] oldOrder) {
            if("bubble".equals(algorithmName)){
                return sortBubble(oldOrder);
            }else if("quick".equals(algorithmName)) {
                return sortQuick(oldOrder);
            }
            return null;
        }
        
        public void setAlgorithmName(String algorithmName) {
            this.algorithmName = algorithmName;
        }
        
        private Integer[] sortBubble(Integer[] oldOrder) {
            for(int i = 1; i < oldOrder.length; i++) {
                for(int j = 0; j < oldOrder.length - i; j++) {
                    if(oldOrder[j] > oldOrder[j + 1]) {
                        Integer temp = oldOrder[j];
                        oldOrder[j] = oldOrder[j + 1];
                        oldOrder[j + 1] = temp;
                    }
                }
            }
            return oldOrder;
        }
        
        private Integer[] sortQuick(Integer[] oldOrder) {
            partSort(oldOrder, 0, oldOrder.length - 1);
            return oldOrder;
        }
        
        private void partSort(Integer[] oldOrder, int start, int end) {
            if(start < end) {
                int middle = swaps(oldOrder, start, end);
                partSort(oldOrder, start, middle);
                partSort(oldOrder, middle + 1, end);
            }
        }
        
        private int swaps(Integer[] oldOrder, int start, int end) {
            Integer temp = oldOrder[start];
            for(;start < end;) {
                for(;start < end && temp <= oldOrder[end]; end--);
                if(start < end) {
                    oldOrder[start] = oldOrder[end];
                    start++;
                }
                for(;start < end && temp > oldOrder[start]; start++);
                if(start < end) {
                    oldOrder[end] = oldOrder[start];
                    end--;
                }
            }
            oldOrder[start] = temp;
            return start;
        }
    }

    print:

    BubbleSort take time:717
    QuickSort take time:14

    上面是我的实现,所有的代码都集中在SortAlgorithm一个class里面。那么试想一下这时候如果我们想再增加一个选择排序,那么我们需要修改SortAlgorithm类,这样我们就违背了 开闭原则 。因此我们要想办法把修改变为增加。那么怎么样才能将修改变为增加呢?通过使用 strategy 可以做到。

    介绍strategy

    • 定义: 定义一系列的算法,将每一个算法封装起来,并且让这些封装的算法之间可以相互替换。该模式可以使算法独立于使用它们的客户而变化。 
    • 类图:

     

    通过上面的类图我们可以总结出一下几点:

    1. 具体算法类 ConcreteStrategyA 和 ConcreteStrategyA 都继承了 Strategy 接口,并且都实现了 algorithm 方法。通过实现接口我们可以很好的实践 开闭原则 ,我们也可以很好的实现扩展
    2. 类 Client 中有一个 Strategy 变量,通过设置这个变量我们可以很容易的转换我们的算法
    • 实现步骤:
    1. 首先定义一个接口
    2. 让所有的算法都实现这个接口
    3. 让客户端持有这个接口

    重构思考题

     那么通过对Strategy的学习,我们来重构下我们上面的问题:

    首先,我们定义一个接口:

    Sort.java:

    public interface Sort {
        Integer[] sort(Integer[] oldOrder);
    }

    然后,我们定义一系列的算法实现上面定义的接口:

    BubbleSort.java:

    public class BubbleSort implements Sort {
        @Override
        public Integer[] sort(Integer[] oldOrder) {
            for(int i = 1; i < oldOrder.length; i++) {
                for(int j = 0; j < oldOrder.length - i; j++) {
                    if(oldOrder[j] > oldOrder[j + 1]) {
                        Integer temp = oldOrder[j];
                        oldOrder[j] = oldOrder[j + 1];
                        oldOrder[j + 1] = temp;
                    }
                }
            }
            return oldOrder;
        }
    }

    QuickSort.java:

    public class QuickSort implements Sort {
        @Override
        public Integer[] sort(Integer[] oldOrder) {
            partSort(oldOrder, 0, oldOrder.length - 1);
            return oldOrder;
        }
        
        private void partSort(Integer[] oldOrder, int start, int end) {
            if(start < end) {
                int middle = swaps(oldOrder, start, end);
                partSort(oldOrder, start, middle);
                partSort(oldOrder, middle + 1, end);
            }
        }
        
        private int swaps(Integer[] oldOrder, int start, int end) {
            Integer temp = oldOrder[start];
            for(;start < end;) {
                for(;start < end && temp <= oldOrder[end]; end--);
                if(start < end) {
                    oldOrder[start] = oldOrder[end];
                    start++;
                }
                for(;start < end && temp > oldOrder[start]; start++);
                if(start < end) {
                    oldOrder[end] = oldOrder[start];
                    end--;
                }
            }
            oldOrder[start] = temp;
            return start;
        }
    }

    最后,我们实现一个算法调用类:

    SortAlgorithm.java:

    public class SortAlgorithm {
        private Sort sort;
        
        public void setSort(Sort sort) {
            this.sort = sort;
        }
        
        public Integer[] executeAlgorithm(Integer[] oldOrder) {
            return sort.sort(oldOrder);
        }
    }

    测试用例:

    Client.java:

    import java.util.Random;
    import java.util.Arrays;
    
    public class Client {
        private static int index = 10;
        private static int randomMax = 100;
        private static Integer[] oldOrder = new Integer[index];
        private static Random random = new Random();
        static {
            for(int i = 0; i < index; i++) {
                oldOrder[i] = random.nextInt(randomMax);
            }
        }
        
        public static void main(String... args) {
            SortAlgorithm sortAlgorithm = new SortAlgorithm();
            Integer[] oldOrder1 = Arrays.copyOf(oldOrder, index);
            Integer[] oldOrder2 = Arrays.copyOf(oldOrder, index);
            
            sortAlgorithm.setSort(new BubbleSort());
            System.out.println(String.format("BubbleSort sort before order:%s", Arrays.asList(oldOrder1).toString()));
            long startTime = System.currentTimeMillis();
            Integer[] newOrder1 = sortAlgorithm.executeAlgorithm(oldOrder1);
            System.out.println(String.format("BubbleSort take time:%s", System.currentTimeMillis() - startTime));
            System.out.println(String.format("BubbleSort sort after order:%s", Arrays.asList(newOrder1).toString()));
            
            sortAlgorithm.setSort(new QuickSort());
            System.out.println(String.format("QuickSort sort before order:%s", Arrays.asList(oldOrder2).toString()));
            startTime = System.currentTimeMillis();
            Integer[] newOrder2 = sortAlgorithm.executeAlgorithm(oldOrder2);
            System.out.println(String.format("QuickSort take time:%s", System.currentTimeMillis() - startTime));
            System.out.println(String.format("QuickSort sort after order:%s", Arrays.asList(newOrder2).toString()));
        }
        
        private static int[] copyOldOrder(int[] oldOrder) {
            int[] result = new int[index];
            for(int i = 0; i < index; i++) {
                result[i] = oldOrder[i];
            }
            return result;
        }
    }

    上面的代码使用了策略模式,通过使用这个模式我们可以很容易的扩展,现在只要我们实现 Sort 接口就可以扩展我们的排序算法。

  • 相关阅读:
    关于使用lombok遇到的问题
    Android自定义View之旅(二)继承View实现自定义
    Android自定义View之旅(一)自定义View的几种方式
    Android中attr属性的类型
    Android Studio 4.0 新功能与优化
    WebView播放视频白屏、不能全屏问题解决
    Android配置Scheme使用浏览器唤起APP的方式,以及不生效问题解决
    Android获取的IMEI只有14位问题解决
    Android偶遇杂症合集(持续更新)
    AndroidKeystore密钥库系统,保证本地加密算法的密钥安全性
  • 原文地址:https://www.cnblogs.com/cafebabe-yun/p/8987956.html
Copyright © 2011-2022 走看看