首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

土话设计模式_策略模式

2012-10-31 
白话设计模式_策略模式策略模式,顾名思意,针对不同的要求采用不同的策略处理问题。  实际的“策略”通常都是

白话设计模式_策略模式

策略模式,顾名思意,针对不同的要求采用不同的策略处理问题。


  实际的“策略”通常都是算法簇,处理同一个问题或者执行同一动作可能有多种策略,而这些策略之间的切换如果以硬编码的方式写在代码中,则相当丑陋,策略模式提供了策略切换的一个动态的机制,即可以运行时指定。


  比如,现在有一个关于鸭子系统,有一个抽象父类Duck, 里面声明了几个鸭子的动作,如 叫、飞、游泳、展示(在这里鸭子动作即是算法簇),针对这个抽象类有多种继承的子类,如MallarDuck(绿头鸭)、RedheadDuck(红头鸭)、RubberDuck(橡胶鸭), 现在问题出来了:并不是每种鸭子都会飞,例子橡胶鸭;每种鸭子的叫声可能并不一样;后一个问题可以通过在子类中重写“叫”这个方法来解决,但前一个问题并不能解决,因为继承是代码复用,导致每种鸭子都包含“飞”这个动作。为了解决这个问题,试将“飞”这个动作从Duck抽象类中分离出去,抽象成一个Flyable接口,需要“飞”这个动作的鸭子则实现这个接口,不需要的不实现这个接口~~表面上好像解决了问题,实现严重破坏了代码复用。因为接口只声明方法,并无实现,这样每种鸭的实现类中都必须重写“飞”这个方法,即使这个实现方式可能是完全一样的,更大的问题在于,如果以后要修改“飞”这个方法,又不得不到每个鸭实现中去一个一个的修改“飞”方法,这显然很不灵活。


软件设计的基本原则:

  一、找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

  二、针对接口编程,而不是针对实现编程。

  三、多用组合,少用继承。


  显然“飞”和“叫”这两个方法是Duck类中变化的部分(假如其他方法都是通用的),运用第一个原则,将它们两个都分离出来,分离成什么呢? 运用第二个原则可得出结论,分离成接口。

?

//飞public interface FlyBehavior {void fly();}//叫public interface QuackBehavior {void quack();}

???   然后是具体的策略,分别实现这两个接口:

//不会飞public class FlyNoWay implements FlyBehavior{public void fly(){System.out.println("Can't fly!");}}//用翅膀飞public class FlyWithWings implements FlyBehavior {public void fly() {System.out.println("fly with wings!");}}//呱呱叫public class QuackGuagua implements QuackBehavior {public void quack() {System.out.println("呱呱叫");}}//不会叫public class QuackNoWay implements QuackBehavior {@Overridepublic void quack() {System.out.println("不会叫...");}}//吱吱叫public class QuackZhizhi implements QuackBehavior {@Overridepublic void quack() {System.out.println("吱吱叫!");}}

?

??????? 客户需要使用策略,这里遵循第三条原则,我们采用组合的方式,在Duck中添加这两个接口的引用,分别在performQuack()和performFly()方法中使用上述接口的引用,调用“叫”动用和“飞”动作,同时声明两个set方法,用来动态的设置这两个引用的运行时对象:

public abstract class Duck {FlyBehavior flyBehavior;QuackBehavior quackBehavior;public void setFlyBehavior(FlyBehavior flyBehavior) {this.flyBehavior = flyBehavior;}public void setQuackBehavior(QuackBehavior quackBehavior) {this.quackBehavior = quackBehavior;}public void swim(){System.out.println("我在游泳...");}public abstract void display();public void performQuack(){quackBehavior.quack();}public void performFly(){flyBehavior.fly();}}

?

  ? 测试:

public class Main {public static void main(String[] args) {Duck duck1 = new MallarDuck();      //动态设置策略duck1.setFlyBehavior(new FlyWithWings());duck1.setQuackBehavior(new QuackZhizhi());duck1.display();duck1.performFly();duck1.performQuack();System.out.println();Duck duck2 = new RubberDuck();      //动态设置策略duck2.setFlyBehavior(new FlyNoWay());duck2.setQuackBehavior(new QuackGuagua());duck2.display();duck2.performFly();duck2.performQuack();}}

?

  ? 总结:

  策略模式的关键在于:分离变化部分、面向接口编程、包含策略接口类型引用变量、运行时动态确定具体策略对象

?

?

热点排行