策略模式
2017-12-24 本文已影响0人
yishurensheng
概念
定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的相互变化独立于算法的客户。
设计原则
- 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起;
- 针对接口编程,而不是针对实现编程;
- 多用组合,少用继承;
要点
- 知道OO基础,并不足以让你设计出良好的OO系统。
- 良好的OO设计必须具备可复用、可扩充、可维护三个特性。
- 模式可以让我们建造出具有良好OO设计质量的系统。
- 模式被认为是历经验证的OO设计经验。
- 模式不是代码,而是针对设计问题的通用解决方案。你可以把它应用到特定应用中。
- 模式不是被发明,而是被发现。
- 大多数的模式和原则,都着眼于软件变化的主题。
- 大多数的模式都允许系统局部改变独立于其他部分。
- 我们常把系统中会变化的部分抽出来封装。
- 模式让开发人员之间有共享的语言,能够最大化沟通的价值。
UML图

代码实现
先把代码贴上去,后面再慢慢解释。
Java版本
此版本的代码只是先实现了MallardDuck和ModelDuck这两个类的鸭子,然后进行了一些测试。剩下的RubberDuck、DecoyDuck以及RedHeadDuck都没有实现,读者如果有兴趣的话,可以自己尝试实现并进行相关的测试。
FlyBehavior.java
package strategy;
/**
* 所有飞行行为类必须实现的接口
* @author ysrs
*
*/
public interface FlyBehavior
{
public void fly();
}
FlyNoWay.java
package strategy;
/**
* 新的FlyBehavior类型,它不具有飞行能力
* @author ysrs
*
*/
public class FlyNoWay implements FlyBehavior
{
// 这是飞行行为的实现,给“不会”飞的鸭子用(包括橡皮鸭和诱饵鸭)
@Override
public void fly()
{
System.out.println("I can't fly!");
}
}
FlyRocketPowered.java
package strategy;
/**
* 新的FlyBehavior类型,它具有火箭般的飞行能力
* @author ysrs
*
*/
public class FlyRocketPowered implements FlyBehavior
{
@Override
public void fly()
{
System.out.println("I'm flying with a rocket!");
}
}
FlyWithWings.java
package strategy;
/**
* 新的FlyBehavior类型,它具有普通的使用翅膀的飞行能力
* @author ysrs
*
*/
public class FlyWithWings implements FlyBehavior
{
// 这是飞行行为的实现,给”真会”飞的鸭子用。。。
@Override
public void fly()
{
System.out.println("I'm flying!!");
}
}
QuackBehavior.java
package strategy;
/**
* 所有呱呱叫行为类必须实现的接口
* @author ysrs
*
*/
public interface QuackBehavior
{
public void quack();
}
Quack.java
package strategy;
/**
* 新的QuackBehavior类型,它具呱呱叫的能力
* @author ysrs
*
*/
public class Quack implements QuackBehavior
{
@Override
public void quack()
{
System.out.println("Quack!");
}
}
Squeak.java
package strategy;
/**
* 新的QuackBehavior类型,它具有吱吱叫的能力
* @author ysrs
*
*/
public class Squeak implements QuackBehavior
{
@Override
public void quack()
{
System.out.println("Squeak");
}
}
MuteQuack.java
package strategy;
/**
* 新的QuackBehavior类型,它不具有叫的能力
* @author ysrs
*
*/
public class MuteQuack implements QuackBehavior
{
@Override
public void quack()
{
System.out.println("<< Silence >>");
}
}
Duck.java
package strategy;
/**
* Duck(鸭子)类
* @author ysrs
*
*/
public abstract class Duck
{
// 为行为接口声明两个引用变量,
// 所有鸭子子类(在同一个package中)都继承它们
protected FlyBehavior flyBehavior;
protected QuackBehavior quackBehavior;
public Duck()
{
}
public abstract void display();
public void performFly()
{
// 委托给行为类
flyBehavior.fly();
}
public void performQuack()
{
// 委托给行为类
quackBehavior.quack();
}
public void swim()
{
System.out.println("All ducks float, even decoys!");
}
// 有了下面这两个函数后,以后就可以“随时”的调用这两个方法来改变鸭子的行为
public void setFlyBehavior(FlyBehavior flyBehavior)
{
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior)
{
this.quackBehavior = quackBehavior;
}
}
MallardDuck.java
package strategy;
/**
* MallardDuck(绿头鸭)类
* @author ysrs
*
*/
public class MallardDuck extends Duck
{
// 因为MallardDuck类是继承Duck类,所以具有
// quackBehavior和flyBehavior实例变量
public MallardDuck()
{
// 绿头鸭使用Quack类处理呱呱叫,所以当performQuack()
// 函数被调用时,叫的职责被委托给Quack对象,而我们得到
// 了真正的呱呱叫,而不是吱吱叫或者叫不出声。
quackBehavior = new Quack();
// 使用FlyWithWings作为FlyBehavior类型
flyBehavior = new FlyWithWings();
}
public void display()
{
System.out.println("I'm a real Mallard duck!");
}
}
ModelDuck.java
package strategy;
/**
* 新的鸭子类型,模型鸭
* @author ysrs
*
*/
public class ModelDuck extends Duck
{
public ModelDuck()
{
// 一开始,我们的模型鸭是不会飞的。
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
public void display()
{
System.out.println("I'm a model duck!");
}
}
MiniDuckSimulator.java
package strategy;
/**
* 测试类,对MallardDuck和ModelDuck两个类进行测试
* @author ysrs
*
*/
public class MiniDuckSimulator
{
public static void main(String[] args)
{
System.out.println("-----------------------------------------");
System.out.println("Test Model MallardDuck!");
Duck mallard = new MallardDuck();
// 这会调用MallardDuck继承来的performQuack()方法,进而委托给该对象的QuackBehavior
// 对象处理,也就是说调用继承来的quackBehavior引用对象的quack()方法。
mallard.performQuack();
// 和performQuack()方法一样
mallard.performFly();
System.out.println("\n-----------------------------------------");
System.out.println("Test Model Duck!");
Duck model = new ModelDuck();
// 第一次调用performFly()函数,会被委托给FlyBehavior对象
// (也就是FlyNoWay实例),该对象是在模型鸭构造函数中设置的。
model.performFly();
// 这会调用继承来的setter方法,把火箭动力飞行的行为设定到模型鸭中。
// 那么,模型鸭就突然具有了火箭动力飞行能力!
model.setFlyBehavior(new FlyRocketPowered());
// 如果设置成功了,就意味着模型鸭可以动态的改变它的飞行行为。
// 如果把行为的实现帮死在鸭子类中,可就无法做到这样了。
model.performFly();
}
}
输出结果:
-----------------------------------------
Test Model MallardDuck!
Quack!
I'm flying!
-----------------------------------------
Test Model Duck!
I can't fly!
I'm flying with a rocket!