写给自己看的设计模式之《策略模式》

定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换

场景

  • 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为
  • 一个系统需要动态地在几种算法中选择一种
  • 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现

优点

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

缺点

  • 策略类会增多
  • 所有策略类都需要对外暴露

使用

1. 创建抽象排序策略类
/**
 * 抽象排序策略类
 *
 * @author dkangel
 */
public abstract class AbstractStrategy {
    
    
    /**
     * 排序方法
     *
     * @param array 待排序的数组
     */
    public abstract void sort(int[] array);

    public void printArray(int[] array) {
    
    
        System.out.print("{ ");
        for (int i : array) {
    
    
            System.out.print(i + " ");
        }
        System.out.println("}");
    }
}

2. 实现快排、冒泡排序子类
/**
 * 快排
 *
 * @author dkangel
 */
public class QuickStrategy extends AbstractStrategy {
    
    

    @Override
    public void sort(int[] array) {
    
    
        System.out.println("use quick sort");
        quickSort(array, 0, array.length - 1);
        super.printArray(array);
    }

    /**
     * 快速排序:选取flag(这里选第一个数),先从右边开始找到小于它的数,交换,再从左边开始找到大于它的数,交换,
     * 这样它就在合适的位置,并把数组分为两个部分,分别重复上述步骤即可。
     * 时间复杂度:O(nlogn)
     * 稳定性:不稳定
     *
     * @param a     待排序数组
     * @param left  leftIndex
     * @param right rightIndex
     */
    private void quickSort(int[] a, int left, int right) {
    
    
        if (left < right) {
    
    
            int flag = a[left];
            int i = left;
            int j = right;
            do {
    
    
                while (a[j] >= flag && j > i) {
    
    
                    j--;
                }
                if (a[j] < flag) {
    
    
                    int tmp = a[j];
                    a[j] = a[left];
                    a[left] = tmp;
                }
                while (a[i] <= flag && i < j) {
    
    
                    i++;
                }
                if (a[i] > flag) {
    
    
                    int tmp = a[i];
                    a[i] = a[j];
                    a[j] = tmp;
                }
            } while (i < j);
            quickSort(a, left, i);
            quickSort(a, i + 1, right);
        }
    }
}

/**
 * 冒泡排序
 *
 * @author dkangel
 */
public class BubbleStrategy extends AbstractStrategy {
    
    

    @Override
    public void sort(int[] array) {
    
    
        System.out.println("use bubble sort.");
        bubbleSort(array);
        super.printArray(array);
    }

    /**
     * 冒泡排序:相邻数进行比较,将大的数沉入数组低端,小的数“冒”到顶端。
     * 时间复杂度为:O(n^2)
     * 稳定性:稳定
     *
     * @param a 待排序数组
     */
    private void bubbleSort(int[] a) {
    
    
        int len = a.length;
        for (int i = 0; i < len - 1; i++) {
    
    
            // 每趟排序结束后数组最后都是最大的值,不用排序,所以j的最大值是len-1-i
            for (int j = 0; j < len - 1 - i; j++) {
    
    
                if (a[j] > a[j + 1]) {
    
    
                    int tmp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = tmp;
                }
            }
        }
    }
}

3. 实现环境角色,链接上下文
/**
 * 环境角色,连接Client与Strategy
 *
 * @author dkangel
 */
public class Context {
    
    
    private AbstractStrategy abstractStrategy;

    public Context(AbstractStrategy abstractStrategy) {
    
    
        this.abstractStrategy = abstractStrategy;
    }

    public void executeStrategy(int[] arrays) {
    
    
        abstractStrategy.sort(arrays);
    }
}

4. 使用
/**
 * 策略模式实用类
 *
 * @author dkangel
 */
public class Main {
    
    
    public static void main(String[] args) {
    
    
        int[] array = new int[]{
    
    3, 1, 9, 5};

        // 使用快排策略
        Context context = new Context(new QuickStrategy());
        context.executeStrategy(array);

        // 使用冒泡排序策略
        context = new Context(new BubbleStrategy());
        context.executeStrategy(array);
    }
}

猜你喜欢

转载自blog.csdn.net/Dkangel/article/details/105848239