设计模式之策略模式

  软件工程师都会学习设计模式,设计模式可以说是前人智慧与经验的结晶,虽然不是哪里都用得到,但是在合适的地方使用合适的设计模式,能够带来巨大的收益。我通过学习《head first 设计模式》,逐渐掌握这些设计方法,本篇是对于策略模式的一点心得。

  策略模式是对算法的包装,是把使用算法的类和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。这样能够很灵活地操作这些方法,通过修改不同子类中的算法就可以达到对应的效果。举个例子,现在有一个Bird类,我们需要的是各种鸟的实例来操作它们。假设Bird这个类有两个个行为,fly和swim,而且show是都有的行为,但是每个子类的show又不一样,那么这么写:

abstract class Bird{
    void fly(){System.out.println("fly...");}void swim(){System.out.println("swim...");}
abstract void show();

}

  看起来没问题,现在业务需要的子类大雁、翠鸟等都妥妥的满足了。然而由于业务扩大,现在需要鸟类实现一个捕食方法,由于觉得所有鸟类都会捕食,而且捕食对象不相同,于是添加了prey的抽象方法,在子类中重载这个方法。后来,业务继续扩大,公司又添加了鸡这个子类,但是这个鸡并不需要捕食,这样一来,就出问题了。强行重载prey方法,然后在里面什么也不做,这显然不是一个明智的方法,那么把prey方法拿走,另外写一个接口Iprey,需要捕食的类就去实现这个接口怎么样,这样子的话,每个子类都要写一个自己的捕食方法,假如捕食方法有变动,所有需要捕食的子类都要改代码,这样也不是个事儿。

  在这里的设计原则有:1、尽量把代码变和不变的部分分割开来;2、针对接口编程,而不是针对实现编程;这里的接口的真正意义是超类型,针对接口编程的真正意义在于多态,利用多态,程序可以针对超类型编程,执行时可以根据实际情况执行到真正的行为,而不会绑死在超类型的行为上。

  于是我们在Iprey接口的基础上,设计了两个类来实现这个接口,其中一个类PreyBehavior,另一个类NoPrey,分别在两个类里有捕食方法和不捕食的方法:

public interface Iprey{
    void prey();
}

class PreyBehavior{
     void prey(){
        System.out.println("prey...");     
    }
}

class NoPrey{
     void prey(){
        System.out.println("No prey...");     
    }
}

现在就可以整合一下Bird的行为了:

public abstract class Bird {
    Iprey preyBehavior;

    void fly() {
        System.out.println("fly...");
    }

    void swim() {
        System.out.println("swim...");
    }
    void performPrey(){
        preyBehavior.prey();
    }
    abstract void show();
}

我们在Bird类里面呢加了个performPrey方法,里面有一个preyBehavior对象,这么做可以让子类选择怎样实现prey方法:

public class Duck extends Bird{
    public Duck(){
        preyBehavior = new NoPrey();
    }
    
    @Override
    void show() {
        System.out.println("duck...");
    }


}

当然,我们可以在Bird类里面加上setPreyBehavior方法来动态控制Prey的动作,这个不提。

posted @ 2017-11-25 14:18  fengshenjingjun  阅读(134)  评论(0编辑  收藏  举报