天天看点

策略设计模式2

一、基本定义  

         策略设计模式:“针对”一组算法,“将”每一个算法封装到具有相同接口的独立的类中,“从而”使它们可以相互替换。

         核心:策略实现相同接口,可以相互替换。即封装的各个算法地位平等,它们具有相同的接口,可以相互进行替换。

策略设计模式2

二、速记

        策略设计模式的重点不是如何实现算法,而是如何组织、调用这些算法。策略设计模式让程序的结构更加灵活,让系统具有更好的灵活性和扩展性,降低需求变动的维护成本。

        核心:封装地位相同的各种算法,让它们可以动态的切换。

        优点:扩展性很好,增加算法只需要增加一个新的策略实现。

        缺点:随着策略越来越多,维护这些的策略也很困难。

        场景:用于计算公式经常变动的业务场景,比如学生的学分GPA的计算。

        注入:在业务中提供一个策略工厂。在工厂的提供的方法中通过条件来判断应该返回哪一个策略,这样业务代码就不用变动。

三、代码实现

        策略设计模式代码有三个主体。

        1.持有抽象策略的引用的类

        2.抽象策略类

        3.具体策略类

        范例一:策略模式经典代码

public class Context {
    private Stategy stategy;

    public Context(Stategy stategy) {
        this.stategy = stategy;
    }

    public int result(){
        return stategy.function();
    }
    //主函数可以视为要被调用的环境,例如Service中,或者是Controller中
    public static void main(String[] args) {
        Context context = new Context(new Stategy1());
        System.out.println(context.result());

    }
}
//抽象策略
interface Stategy{
    int function();
}
//具体三种策略实现
class Stategy1 implements  Stategy{

    @Override
    public int function() {
        return 1;
    }
}
class Stategy2 implements  Stategy{

    @Override
    public int function() {
        return 2;
    }
}
class Stategy3 implements  Stategy{

    @Override
    public int function() {
        return 3;
    }
}      

        这个例子里面Context类持有着抽象策略的引用,由构造函数接收抽象策略实现类。Context调用的result()方法,其实就是包裹的策略的function()方法。根据具体情况,选择不同的策略的实现类,传递给Context类的构造器。

        范例二:策略模式与简单工厂模式结合

        这种方式更加适合与MVC模式。Controller代码中不直接生成相关策略,根据前台传递过来的参数,交由Context类的构造函数,在Context类的内部进行选择具体的实现类。Controller层里面的代码只需要知道Context类,根本不需要知道具体的策略类。在发生需求变动的时候,我们修改的类是Context类的构造函数,修改switch()语句,因此Controller层的代码不需要变动。代码如下:

public class Context {
    private Stategy stategy;
    public Context(int i) {
        switch (i){
            case 1:{
                stategy = new Stategy1();
                break;
            }
            case 2:{
                stategy = new Stategy2();
                break;
            }
            case 3: {
                stategy = new Stategy3();
                break;
            }
            default:{
                stategy = new Stategy1();
            }
        }

    }

    public int result(){
        return stategy.function();
    }

    //此主函数可以看作是要实际应用的环境,比如某个Controller中
    public static void main(String[] args) {
        Context context = new Context(3);//这个构造函数的参数由前端传递过来
        System.out.println("结果是:"+context.result());

    }
}
//策略
interface Stategy{
    int function();
}
//具体实现三种
class Stategy1 implements  Stategy{

    @Override
    public int function() {
        return 1;
    }
}
class Stategy2 implements  Stategy{

    @Override
    public int function() {
        return 2;
    }
}
class Stategy3 implements  Stategy{

    @Override
    public int function() {
        return 3;
    }
}      

        上述代码可以看到,我们的主函数中,只有Context类的代码,没有出现具体的策略类。调用Context的result()方法,实际上就是包裹调用策略类的function()方法。这个时候,如果出现需求变动,我们Controller层的代码是不需要变动的,修改的是Context类中的switch()语句。

        有同事说策略模式的好处之一就是可以避免 if - else 语句,我是不赞成的,因为不管怎么说,策略模式是根据不同的情况选择不同的策略,那么这个过程必然会有 条件选择语句。if - else 语句也好,swicth语句也好,条件语句经过判断,选择出具体的实现类,因此它们在策略模式中是不可避免的。

四、优缺点

        优点:由于策略模式的扩展性与灵活性,代码变得便于维护。在实际中,从前端接收一个参数,然后调用简单工厂的构造函数,在简单工厂内部创建这个策略的实例对象,调用简单工厂的方法返回结果即可。代码可参考第二个例子。

        扩展性体现在,当需求发生变动的时候,我们可以添加新的策略实现类,不用修改已有的策略类。

        灵活性体现在,我们可以根据需求,切换我们的策略类。

        缺点:策略模式因为需要将每一个策略都封装成具有相同接口的独立的类,如果当前系统中策略很多,无异于增加了代码开发的量。另外,在调用这些策略的时候,需要对每一个策略都要了解,增加了系统的复杂性。

刻意练习

        (1)策略设计模式的核心。

        (2)策略设计模式的优点。

        (3)策略设计模式的缺点。

        (4)使用场景。

        (5)类图

        (6)策略类怎么注入到业务中

分割线--------------------------------------------------------------------------------------------

下一篇:工厂设计模式3