策略模式(封装可以互换的行为,并使用委托来决定要使用哪一个)

2017-11-06  本文已影响0人  钉某人
源码地址 https://github.com/DingMouRen/DesignPattern
策略模式.png
定义

策略模式定义一系列的算法,把它们一个个封装起来 , 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

使用场景
协作
举个栗子

一个学生要获取到数字6,他有多种算法。

一般做法:假设在类Student中实现获取到数字6的算法getNumberSix(),如果老师要求使用相加的方式来实现,那么我们就用相加的方式来实现;没多久老师又让我们用相乘的方式来实现,好吧,我们再写相乘方式的算法;又没多久老师让我再以相减的方式来实现,我们又得回到Student类添加if-else,又对代码进行修改,违背了OO的开闭原则,设计的类应该是对扩展开放,对修改关闭。

 //获取到数字6
    public void getNumberSix(String str){
        if (str.equals("相加")){
            addMethod();//相加的方式获取到数字6
        }else if (str.equals("相乘")){
            multiMethod();//相乘的方式获取到数字6
        }else if (str.equals("相减")){
            subtractMethod();//通过相减的方式获取到数字6
        }
    }

思考:我们想让Student类一旦编写结束,尽量不要再修改它,获取到数字6的算法有多种,怎么办呢?考虑到java的封装与多态,我们可以将算法封装成一个类,再向上抽象,抽象成一个接口,这个接口有一个方法(获取数字6的算法),每一个实现类都要实现这个方法。我们通过聚合的方式,将接口通过类Student的构造函数作为一个成员变量置于Student类中,在Student类的getNumberSix()方法中调用接口的方法。接口实现类负责具体算法的实现,比如相加获取6,相乘获取6,Studnet类要获取数字6的话,就在创建Student时传入接口实现类,java多态自动向上转型,传入的类型都是接口类型的,然后在调用getNumberSix()时,java的向下转型和运行时类型判断就起到了关键作用,这时调用的方法就是当时传入的接口实现类的方法。如果老师还想要其他的算法要求的话,只要实现接口的方法,传入新的算法就行了,这样就非常容易扩展了,也不用修改Student类。为了可以动态的更换算法,我们添加一个set方法,就可以实现动态更换算法了。

//学生
public class Student {
    private Stragety stragety;//策略的抽象,也可以称作泛化

    public Student(Stragety stragety) {
        this.stragety = stragety;
    }

    /**
     * 获取数字6
     */
    public void getNumberSix(){
        int result = stragety.calculate();
        System.out.println(result == 6 ? "获取的数字正确":"获取的数字不正确,获取到的数字是"+result);
    }

    /**
     * 可以动态的更换策略
     * @param stragety
     */
    public void setStragety(Stragety stragety) {
        this.stragety = stragety;
    }

}

//策略的抽象
public interface Stragety {
    int calculate();//获取到数字6的方法抽象
}
//具体策略的实现:相加
public class StragetyAdd implements Stragety {
    /**
     * 具体算法的实现:通过相加的方式获取到数字6
     * @return
     */
    @Override
    public int calculate() {
        int result = 0;
        for (int i = 0; i < 6; i++) {
            result += 1;
        }
        return result;
    }
}
//具体策略的实现:相乘的
public class StargetyMultiply implements Stragety{
    /**
     * 具体算法的实现:通过相乘的方式获取到数字6
     * @return
     */
    @Override
    public int calculate() {
        int result = 2 * 3;
        return result;
    }
}

使用

public static void main(String[] args) {
        //创建对象
        Student student = new Student(new StragetyAdd());
        //获取到数字6
        student.getNumberSix();
        //动态更换策略
        student.setStragety(new StargetyMultiply());
        student.getNumberSix();
    }
总结

优点

上一篇 下一篇

猜你喜欢

热点阅读