Java设计模式之策略模式

来源:互联网 发布:游族网络 林奇车祸 编辑:程序博客网 时间:2024/06/07 06:35

看了许多篇关于策略模式的博客,大多都是大同小异,没有实质性的理解帮助,包括看《Head First 设计模式》中的例子,一开始看的时候也是云里雾里,找到一篇博客结合这个例子讲的比较容易理解:http://www.cnblogs.com/justinw/archive/2007/02/06/641414.html
自己试着按照其提供的思路敲了一遍书中的代码,并简化了一下。
策略模式的设计原则:
1.找出应用中可能需要变化之处,把它们独立起来,不要和那些不需要变化的代码混在一起;
2.针对接口编程,而不是针对对象编程;
3.多用组合,少用继承。
简单来说策略模式就是定义算法族,分别封装起来,让算法的变化独立于使用算法的客户。
在本例中,只定义了一个算法族,鸭子的飞行方式就是需要变化的部分,将其独立起来。
定义一个飞行方式接口,这个接口有很多不同的实现。

定义一个抽象类Duck

public abstract class Duck {    //每个鸭子的外观各不相同子类对象必须重写    public abstract void display();    //所有的鸭子都会游泳,子类对象直接继承    public void swim(){        System.out.println("Swimming!");    }    //鸭子可以利用设置方法根据自身情况设置飞行方式    FlyWay flyWay;    public void setFlyWay(FlyWay flyWay){        this.flyWay=flyWay;    }    public void doFly(){        flyWay.fly();    }}

定义一个飞行方式接口

public interface FlyWay {    public void fly();}

有两种具体实现

public class FlyWithoutWings implements FlyWay {    @Override    public void fly() {        System.out.println("fly without wings");    }}
public class FlyWithWings implements FlyWay {    @Override    public void fly() {        System.out.println("fly with wings");       }}

鸭子具体实现类FirstDuck

public class FirstDuck extends Duck{    @Override    public void display() {        System.out.println("A red duck");    }}

测试类:

public class StrategyDemo {    public static void main(String[] args) {        Duck firstDuck=new FirstDuck();        firstDuck.display();        firstDuck.swim();        firstDuck.setFlyWay(new FlyWithWings());//设置飞行方式        firstDuck.doFly();    }}

输出:
A red duck
Swimming!
fly with wings

上面我们已经看过了Strategy模式的详细介绍,下面我们再来简单说说这个模式的优缺点吧只有在特定的场景下才能发挥其功效。我们要使用好模式,就必须熟知各个模式的应用场景。
对于Strategy模式来说,主要有这些应用场景:
1、 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。(例如FlyWay)
2、 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。(例如FlyWay的具体实现可任意变化或扩充)
3、 对客户(Duck)隐藏具体策略(算法)的实现细节,彼此完全独立。

对于Strategy模式来说,
有如下优点:
1、 提供了一种替代继承的方法,而且既保持了继承的优点(代码重用)还比继承更灵活(算法独立,可以任意扩展)。
2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
缺点主要有两个:
1.维护各个策略类会给开发带来额外开销,可能大家在这方面都有经验:一般来说,策略类的数量超过5个,就比较令人头疼了。
2.必须对客户端(调用者)暴露所有的策略类,因为使用哪种策略是由客户端来决定的,因此,客户端应该知道有什么策略,并且了解各种策略之间的区别,否则,后果很严重。例如,有一个排序算法的策略模式,提供了快速排序、冒泡排序、选择排序这三种算法,客户端在使用这些算法之前,是不是先要明白这三种算法的适用情况?就这一点来说是有悖于迪米特法则的。
注:迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简写LKP),就是说一个对象应当对其他对象有尽可能少的了解,不和陌生人说话。英文简写为: LoD.

0 0