设计模式之策略模式

来源:互联网 发布:c语言怎么取反 编辑:程序博客网 时间:2024/05/24 06:03

设计模式不拘泥于语言,不拘泥于特定的场景,传达的是一种思想,在实际学习中我们或多或少的接触所谓的设计模式的名字,为了学设计模式也不得不去看很多样例,因为抽象的思想很难表达,而语言是能够具体表达的东西,无论如何,我们最后设计出的目标都是要复合面向对象几大基本原则的。

  • 开闭原则
  • 接口隔离
  • 依赖倒置
  • 里氏替换
  • 单一职责
  • 最小知识
  • 面向接口编程与尽量用组合去替换继承关系复用
    满足这些原则的OOA被公认为是容易维护和扩展开发的系统。设计模式无非是遵循了这些原则的基础上对一些比较典型的场景进行了归纳总结。
    好了,复习完了设计模式的基本概念,我们这次来谈谈策略模式。经常我们在业务场景中同一种方法有不同的实现方式,这个时候我们可能会通过传入参数的方式然后通过if else去判断到底执行怎样的操作,但是我们知道if else如果太多是非常不容易维护的,而且如果要添加新的实现方式又要去修改原来的程序,这非常不符合OCP原则。这个时候我们就可以采用策略模式。
    首先我们来看策略模式的UML图:
    这里写图片描述
    这里涉及到的角色有:

  • 策略接口

  • 封装策略的类:维护策略接口的引用
  • 实现策略的类,一般有多个
    然后我们在客户端调用封装策略的类。首先我们看个例子,我们客户端要对一个数组进行排序,但是由于不同的场景我们想要不同的排序算法。一般情况下我们会采用以下的编写方式:
    /**     * @Description : 不同的算法实现     * @param : method : 0-冒泡, 1-插入, 2-堆排序, 3 快速排序     */    public void sort(int[] array, int method) {        if (method == 0) {            System.out.println("冒泡排序");        } else if (method == 1) {            System.out.println("插入排序");        } else if (method == 2) {            System.out.println("堆排序");        } else if (method == 3) {            System.out.println("快速排序");        }    }    // 客户端调用        int[] array = new int[]{1,2,3};        sort(array, 0);        sort(array, 1);

这样选择了不同的算法,但是这样是不容易维护的。我们如果采用策略模式:
首先我们设计一个策略的接口,定义规范,就是这个算法,这里可能是一部分过程的组合,因此这里也时常会跟模板方法模式结合起来,那这里接口就该写成抽象类。

// 策略类interface Sort {    // 定义规范    void processArray(int[] array);}

// 三个实现算法的三个类:

class Bubble implements Sort {    @Override    public void processArray(int[] array) {        System.out.println("排序算法");    }}class Insert implements Sort {    @Override    public void processArray(int[] array) {        System.out.println("插入排序");    }}class HeapSort implements Sort {    @Override    public void processArray(int[] array) {        System.out.println("堆排序");    }}

然后定义一个封装策略的类:

class ProcessData {    // 这里维护一个策略类的引用    Sort sort;    ProcessData(Sort sort) {        this.sort = sort;    }    public Sort getSort() {        return sort;    }    public void setSort(Sort sort) {        this.sort = sort;    }    // 执行    public void execute(int[] array) {        sort.processArray(array);    }}

客户端调用:

        int[] array = new int[] { 1, 2, 3 };        ProcessData processData = new ProcessData(new Bubble());        processData.execute(array);        // 新的算法        processData.setSort(new Insert());        processData.execute(array);        processData.setSort(new HeapSort());        processData.execute(array);

运行结果:

排序算法插入排序堆排序

我们可以增加新的排序方式而几乎不用去修改原来的代码,这样的好处是显而易见的。接下来谈谈策略模式的优缺点:
优点:策略模式实现了开闭原则,避免了大量的if else维护。容易扩展。
缺点:客户端必须要知道有哪些具体的策略,这点违迪米特法则。如果策略过多,类的数量比较大,过度设计。

使用场景:经常我们使用一些函数,都是执行的一件事情,但是做这件事情的方式很多,而且可能还会不断的改变或则增加,其他部分都一样,只是实现部分会有些不同,这样我们就可以采用策略模式来封装这种算法。策略模式一般会结合模板方法工厂方法去使用。
以下给出结合模板方法使用的代码:

// 模板方法结合策略模式abstract class Sort {    // 模板方法, sort方法是抽象类,具体实现类去实现    public void doSomething(int[] array) {        System.out.println("准备好排序之前的工作");        System.out.println(sort(array) + " 排序完毕..");        System.out.println("排序之后的工作");     }    public abstract String sort(int[] array);}class Bubble extends Sort {    @Override    public String sort(int[] array) {        return "冒泡法...";    }}class Insert extends Sort {    @Override    public String sort(int[] array) {        return "插入排序...";    }}class ProcessData {    Sort sort;    public ProcessData(Sort sort) {        this.sort = sort;    }    public void execute(int[] array) {        sort.doSomething(array);    }}

客户端调用:

        int[] array = new int[] { 1, 2, 3 };        ProcessData processData = new ProcessData(new Bubble());        processData.execute(array);

运行结果:

准备好排序之前的工作冒泡法... 排序完毕..排序之后的工作
0 0
原创粉丝点击