策略设计模式

策略设计模式


1. 简单介绍

策略模式(Strategy)是一种行为型设计模式。该模式定义了一个算法簇,用不同的类分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。很好的满足了开闭原则。

2. 使用场景
  • 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为
  • 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现
  • 对客户隐藏具体策略(算法)的实现细节,彼此完全独立
3. 场景举例

我们在对一个数组进行排序时,通常会使用Arrays.sort(T[ ] a, Comparator<? super T> c)方法。该方法通过传入一个Comparator,指定数组的排序算法。这是策略模式的一个典型的使用场景。抽离出需要动态变化的排序算法部分(数组的排序算法),根据用户的需要,传入不同的Comparator对数组采用不同的算法进行排序。当用户需要采用新的排序算法时,只需要新增一个排序算法,传入sort方法中即可,很好的满足了开闭原则。

4. UML类图

策略模式UML类图

5. 具体实现

描述

  • 背景:对数组进行排序,通过策略模式来实现不同场景下的切换不同排序算法进行排序
  • Strategy:策略类,定义了排序算法的接口
  • BubbleSortStrategy:具体的策略类,冒泡排序
  • InsertSortStrategy:具体的策略类,插入排序
  • Context:上下文,维护着Strategy
  • Client:客户端

代码实现

Strategy.java

/**
 * 策略类,定义了排序算法的接口
 */
public interface Strategy<T extends Comparable> {

    void sort(T[] t);

    default void swap(T[] t, int leftIdx, int rightIdx) {
        T tempT = t[leftIdx];
        t[leftIdx] = t[rightIdx];
        t[rightIdx] = tempT;
    }
}

BubbleSortStrategy.java

/**
 * 冒泡排序
 */  
public class BubbleSortStrategy<T extends Comparable> implements Strategy<T> {
    @Override
    public void sort(T[] t) {

        for (int i = 0; i < t.length; i++) {
            for (int j = 0; j < t.length - i - 1; j++) {
                if (t[i].compareTo(t[j]) > 0) {
                    swap(t, i, j);
                }
            }
        }
    }
}

InsertSortStrategy.java

/**
 * 插入排序
 */
public class InsertSortStrategy<T extends Comparable> implements Strategy<T> {
    @Override
    public void sort(T[] t) {
        for (int i = 1; i < t.length; i++) {
            for (int j = i; j > 0; j--) {
                if (t[j].compareTo(t[j - 1]) > 0) {
                    swap(t, j, j - 1);
                }
            }
        }
    }
}

Context.java

/**
 * 上下文
 */
public class Context {

    /**
     * 具体的排序策略由用户传入,利用了多态的特性
     */
    public static <T extends Comparable> void sortWithStrategy(T[] t, Strategy strategy) {
        strategy.sort(t);
    }
}

Client.java

/**
 * 客户端
 */
public class Client {

    public static void main(String[] args) {

        // 创建待排序数组
        Integer[] beSortedArr = new Integer[]{1, 5, 9, 7, 5, 3, 6, 5, 4, 8, 5, 2};

        // 场景一:使用冒泡排序对数据进行排序
        Context.sortWithStrategy(beSortedArr, new BubbleSortStrategy<Integer>());
        for (Integer integer1 : beSortedArr) {
            System.out.println(integer1);
        }

        // 场景二:使用插入排序对数组进行排序
        // 利用多态的特性,改变排序的策略(算法)
        Context.sortWithStrategy(beSortedArr, new InsertSortStrategy<Integer>());
    }
}
7. 源码展示

JDK中的Arrays.sort(T[ ] a, Comparator<? super T> c)方法的实现采用策略设计模式。该方法的作用是对数组a进行排序,而具体排序的策略则是通过用户传入的Comparator决定的。其中源码如下:

Comparator.java

/**
 * 对应策略模式中Strategy接口,定义了排序算法compare方法
 */ 
public interface Comparator<T> {
    int compare(T o1, T o2);
}

TimSort.java

/**
 * 对应Context角色,持有Comparator(即策略类)的引用
 */
class TimSort<T> { 
    /**
     * 聚合Comparator接口,通过私有构造方法传入
     */
    private final Comparator<? super T> c;
    
    /**
     * 私有构造方法,内部调用传入Comparator
     */
    private TimSort(T[] a, Comparator<? super T> c, T[] work, int workBase, int workLen) {
        this.a = a;
        // 为Comparator赋值
        this.c = c;

        // 其余代码略
    } 
    
    /**
     * 用户可以根据要求,传入具体的策略类作为数据排序的比较器
     * 程序在运行时会使用用户传入的比较器作为数组排序算法
     */
    public static <T> void sort(T[] a, Comparator<? super T> c) {
        if (c == null) {
            sort(a);
        } else {
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a, c);
            else
                TimSort.sort(a, 0, a.length, c, null, 0, 0);
        }
    }

注: 具体的策略类(ConcreteStratagy),由用户自己进行实现。在使用Arrays.sort()方法时,传入即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值