Java设计模式之策略模式

来源:互联网 发布:常州网络推广 编辑:程序博客网 时间:2024/06/10 13:02

策略模式(strategy pattern):定义了算法族,分别封闭起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户.

策略模式的结构

  策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。下面就以一个示意性的实现讲解策略模式实例的结构。


这个模式涉及到三个角色:

环境(Context)角色:持有一个Strategy的引用。

抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。

具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。


接下来用形象生动的案例让大家明白。现在公司里面已经开发了一款应用,主要是展示大自然中的狗的应用,在市场中得到了很大的反响,获得了很大的成功。


狗的抽象类:

/** * 超类,所有的狗都要继承此类 * @author JUN * */public abstract class Dog {//发出叫声public void quack(){System.out.println("旺旺旺");}//显示狗的外观public abstract void display();}

描述二哈类:

public class FoolishDog extends Dog {public FoolishDog() {super();}@Overridepublic void display() {System.out.println("我是二哈,我老是做一些奇怪的表情!");}public void quack(){System.out.println("啊嗚嗚嗚~~~");}}

描述柴犬类:

public class YellowDog extends Dog {public YellowDog() {super();}@Overridepublic void display() {System.out.println("我是柴犬,我全身黃黃的");}}


但是为了应对激烈的竞争,公司需要变革才能保持已有的优势。这是就需要对产品新增一些新的功能。比如给狗增加飞行、上天的能力。


那么有什么方法可以给应用很灵活的增加这些功能呢?

继承:在父类中提供实现方法,子类通过继承获得父类中的飞行或者上天的行为。
虽然简单易用(粗暴丑陋),在已有应用中课快速添加飞行的能力。但是不具有灵活性,对未来变更支持差。
需要在子类中覆写飞行方法已提供新的飞行行为。这很容易造成错误。

抽象方法:在父类中提供抽象方法,强迫子类实现自己的飞行行为。
虽然足够灵活。但是很麻烦累人,每个子类都要实现一遍代码,即使相同的行为也不例外。代码重复,没有复用代码。


那么还有什么更好的办法吗?

当我们Java学习到一定程度就会明白:复合优于继承,多用组合,少用继承。

那么该如何使用策略模式呢?接下来就进行代码操作:

添加一个策略接口:

/** * 策略接口 *  * @author JUN *  */public interface FlyingStrategy {void performFly();}

在狗的抽象类中增加红框中的代码:


上述的柴犬和二哈都是自然界中真实的狗,接下来如果我们要给狗增加不能飞行、飞行和上天的行为,那么我们现在来添加一下具体的策略角色,具体策略角色需要实现我们的策略接口

不能飞行的功能:

public class FlyNoWay implements FlyingStrategy {@Overridepublic void performFly() {System.out.println("我是走地狗!");}}

可以飞行的功能:

public class FlyWithWin implements FlyingStrategy {@Overridepublic void performFly() {System.out.println("我有翅膀,我會飛!");}}

可以上太空的功能:

public class FlyWithRocket implements FlyingStrategy {@Overridepublic void performFly() {System.out.println("我坐太空火箭!");}}

这时我们策略模式中的角色都有了:


接下来我们需要给柴犬和二哈添加一个相对应的行为,由于它们都是自然界中真实的狗都不能飞行,所以我们只需在构造方法中加一行代码就可以:

二哈类的变化:


柴犬类的变化:


好了,以上都准备完毕,接下来我们来感受一下策略模式的好处。公司下一阶段的项目将是开发会飞行的狗,我们只需这样添加一个类:

天狗类:

public class FlyDog extends Dog {public FlyDog() {super();super.setFlyingStrategy(new FlyWithWin());}@Overridepublic void display() {System.out.println("我是天狗,天狗望月!");}}

好了天狗类的产品已经完成,再下一阶段公司打算让狗上太空,那么我们依旧简单的这样添加一个类:

太空狗类:

public class SpaceDog extends Dog {public SpaceDog() {super();super.setFlyingStrategy(new FlyWithRocket());}@Overridepublic void display() {System.out.println("我是太空狗,太空狗登月!");}public void quack() {System.out.println("我通过无线电与你通信");}}

接下来我们写一个狗的测试类:

public class DogTest {public static void main(String[] args) {System.out.println("测试开始");System.out.println("*******");Dog dog = null;dog = new YellowDog();  //柴犬//dog = new FoolishDog();  //二哈//dog = new FlyDog();     //天狗//dog = new SpaceDog();   //太空狗dog.display();dog.quack();dog.fly();System.out.println("***********");System.out.println("测试完成");}}

逐一运行,柴犬和二哈的运行结果:

     

天狗和太空狗的运行结果:

    


现在有感觉到策略模式的好处了吧!这里建议我们多去代码实现一下,体验一下才能牢记。
最后我们总结一下:
策略模式的优点:
1、使用了组合,使架构更加灵活
2、富有弹性,可以较好的应对变化(开闭原则)
3、更好的代码复用(相对于继承)
4、消除大量的条件语句

缺点
1、客户代码需要了解每个策略实现的细节
2、增加了对象的数目

策略模式的使用场景:
1、许多相关的类仅仅是行为差异
2、运行是选取不同的算法变体
3、通过条件语句在多个分支中选取一个

0 0
原创粉丝点击