策略模式 (Strategy Pattern)

来源:互联网 发布:汽车导航软件下载 编辑:程序博客网 时间:2024/05/22 05:12

策略模式 (Strategy Pattern)

定义:定义了算法簇,分别封装起来,让它们之间可以相互替换,此模式让算法的变法独立于使用算法的客户。

使用《Head First Design Pattern》 书中Duck的例子分析下上述定义

Duck(abstract class) – 使用算法(飞行FlyBehavior,鸣叫QuackBehavior)

public interfaceFlyBehavior {

   void fly();

}

public interfaceQuackBehavior {

   void quack();

}

基于这两个接口定义一组类,构成了算法簇,飞行方式、鸣叫方式都分别有很多种。

public classFlyWithWing implements FlyBehavior {

   @Override

   public void fly() {

      System.out.println("I fly with the wing.");

   }

}

这就是算法簇中的一个算法并封装(类FlyWithWing封装了Fly算法簇的一种算法)起来,定义了一种飞行方式Fly with Wing 用翅膀飞。

既然是算法簇,当然还以可以有其它的算法。例:

public classFlyNoWay implementsFlyBehavior {

   @Override

   public void fly() {

      System.out.println("I can't fly.");

   }

}

FlyNoWay也是Fly算法簇的一个算法。

/*

 * Duck 鸭子类,FlyBehavior算法簇的客户

 * FlyBehavior簇中添加和删除算法(例如:FlyNoWayFlyWithWing...

 * 都对Duck类无影响,无需修改客户Duck代码

 * CauZ Duck 使用 has-a(组合FlyBehavior而不是 is-a

 */

public abstractclassDuck {

   private FlyBehaviorflyBehavior;

   public voidsetFlyBehavior(FlyBehavior flyBehavior){

      this.flyBehavior=flyBehavior;

   }

//other code here

}

 

//测试方法

   public static void main(String...args){

      FlyBehaviorflyWithWing = newFlyWithWing();

      DuckredHeadDuck = newRedHeadDuck();

      redHeadDuck.setFlyBehavior(flyWithWing);

      redHeadDuck.display();

      redHeadDuck.performFly();

      System.out.println("-----------------------------");

      //切换redHeadDuck飞行行为

      redHeadDuck.setFlyBehavior(flyNoWay);

      redHeadDuck.display();

      redHeadDuck.performFly();

}

我们可以通过setFlyBehavior在运行时设定飞行行为,可以是来着Fly算法簇中的任意一个算法(都实现了FlyBehavior接口)。

duck.setFlyBehavior(flyBehaviorMagic);//实现了算法切换

但是我们的客户Duck不知晓(代码层次)它所关联的具体Fly行为是什么,算法的切换亦是不会影响到客户Duck。


没有使用策略模式的Duck
/**
 * 这是所有鸭子的父类,其中包含了鸭子的一些基本行为
 * 如:display、quack、fly
 */
public abstract class Duck {
/**
* 抽象的display方法,子类分别提供自己的实现。 
*/
public abstract void display();

public void quack(){
//假设大多鸭子都zhizhi的叫,这是为什么没有设置为抽象方法的原因
System.out.println("zhizhi");
}
public void fly(){
System.out.println("I am flying");
}
}


/*
 * 分析一:以上基本行为几乎是所有鸭子都具有的,所以抽象成鸭子超类 Duck。
 * 这样Concrete类就可以继承Duck,实现不同的鸭子
 * 问题: 但是,对于每个行为不同的鸭子可能不一样,叫声不同、飞行方式不同。
 * 基于以上问题:为什么不把quack和fly设置为抽象呢?不然Concrete类就可能继承到错误的行为(如果不覆盖super类方法)。
 * 抽象方法和接口是一种设计行为,不利于代码重用,对于Duck来说这样的设计除了应用多态这一点就一无是处了。没有体现出继承的优点。
 * 继承无法排除特例,例如塑料鸭子不会飞,但是却错误的继承了fly方法,这是必须在塑料鸭子PlasticDuck中覆盖fly方法,明确什么事情都不做。
 * 
 * 
 * 分析二:关于扩展升级
 * Duck 添加新的行为,比如:现在加入layEggs()//产蛋行为
 * 我们就要在Duck加入 layEggs方法,但是公鸭子很塑料鸭子不会啊,这不是为难鸭子么?
 * 加入这个方法,就必须手动覆盖掉其他N多非活生生母鸭子的layEggs行为,天知道这样会不会把手指累折了。
 */

 /*
 * 设计模式:无非就是减少依赖、封装变化、提高重用性,最终开发人员得益于开发效率提高,程序保证了健壮性。
 * 策略模式侧重对变化的封装。
 */

 

 

 

 

 

 

 

 

 

0 0
原创粉丝点击