策略模式
定义算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。(虽然能理解意思,但真心记不住= =)
策略模式其实不难,顾名思义就是更改策略(策略接口下的子类)。首先是需要一个策略接口:Strategy,可以有n个子类实现此接口;其次是
拥有此接口对象(注意是接口对象,而不是任意的子类)的客户端,那么客户端可以在运行时根据需要选择策略(子类)。
这样做的好处:
1. 维护方便:若策略经常改变,则更换策略便是;若出现新策略,那么实现一个继承策略接口的子类便可。其实这都可以归结为针对接口编程带来的好处。
2. 强大的组合:想象一下,若有n个策略接口,每个策略接口都有m个子类。客户端只要维护n个策略接口对象,在运行时更改具体子类,那么其组合效应 是非常惊人的,可以很方便的根据实际需要组装出各种接口组合。
说了这么多,写一个例子:
有这样一个场景:有3种鸭子(为毛是鸭子呢- -):小鸭、会飞的老鸭(这个更囧吧)、玩具鸭。它们具有两类行为:叫和飞。具体行为分配如下列表:
quack fly
小鸭: 不会叫 不会飞
老鸭: 嘎嘎叫 会飞
橡皮鸭: 吱吱叫 不会飞
一种常见的做法是:写一个Duck的抽象类,包括quack()和fly()方法(应当是抽象的,因为每种鸭子的行为不同),然后这三种鸭子继承Duck抽象类。这样做的问题:1. 代码无法复用。当两种鸭子的某一行为相同时,你只能去copy代码;当增加一种新鸭子时,也只能重写其行为。 2. 当鸭子的行为改变时,很显然只能修改源代码!这样不好嘛?好是好,可有没有想过运行时修改,而不用修改源代码呢!
现在就用策略模式来改变这一现状吧:)
1. FlyBehaviour接口及其两个子类CanFly和CantFly,分别代表“会飞”和“不会飞”。
1 package StrategyPattern; 2 /* 3 * 飞行接口 4 */ 5 public interface FlyBehaviour { 6 public void fly(); 7 } 8 9 10 11 package StrategyPattern; 12 13 public class CanFly implements FlyBehaviour { 14 15 @Override 16 public void fly() { 17 // TODO Auto-generated method stub 18 System.out.print("会飞"); 19 } 20 21 } 22 23 24 25 package StrategyPattern; 26 27 public class CantFly implements FlyBehaviour { 28 29 @Override 30 public void fly() { 31 // TODO Auto-generated method stub 32 System.out.print("不会飞"); 33 } 34 35 }
2. QuackBehaviour接口及其三个子类NoQuack,GagaQuack和ZhizhiQuack,分别代表“不会叫”、“嘎嘎叫”、“吱吱叫”。
1 package StrategyPattern; 2 /** 3 * 叫行为。 4 * @author Administrator 5 * 6 */ 7 public interface QuackBehaviour { 8 public void quack(); 9 } 10 11 12 package StrategyPattern; 13 14 public class NoQuack implements QuackBehaviour { 15 16 @Override 17 public void quack() { 18 // TODO Auto-generated method stub 19 System.out.print("不会叫"); 20 } 21 22 } 23 24 package StrategyPattern; 25 26 public class GagaQuack implements QuackBehaviour { 27 28 @Override 29 public void quack() { 30 // TODO Auto-generated method stub 31 System.out.print("嘎嘎叫"); 32 } 33 34 } 35 36 37 package StrategyPattern; 38 39 public class ZhizhiQuack implements QuackBehaviour { 40 41 @Override 42 public void quack() { 43 // TODO Auto-generated method stub 44 System.out.print("吱吱叫"); 45 } 46 47 }
3. Duck抽象类,含有FlyBehaviour和QuackBehaviour的两个接口对象。及其三个子类,LittleDuck、OldDuck和RubbDuck。
1 package StrategyPattern; 2 3 import java.awt.DisplayMode; 4 5 /** 6 * duck的抽象父类。 7 * @author Administrator 8 * 9 */ 10 public abstract class Duck { 11 12 FlyBehaviour flyBh; 13 QuackBehaviour quackBh; 14 15 public Duck(FlyBehaviour fly, QuackBehaviour quack) { 16 this.flyBh = fly; 17 this.quackBh = quack; 18 } 19 20 public void setFlyBehaviour(FlyBehaviour fly) { 21 this.flyBh = fly; 22 } 23 24 public void setQuackBehaviour(QuackBehaviour quack) { 25 this.quackBh = quack; 26 } 27 28 public void performFly() { 29 flyBh.fly(); 30 } 31 32 public void peformQuack() { 33 quackBh.quack(); 34 } 35 36 public abstract void display(); 37 38 } 39 40 41 42 package StrategyPattern; 43 44 public class LittleDuck extends Duck { 45 46 public LittleDuck(FlyBehaviour fly, QuackBehaviour quack) { 47 super(fly, quack); 48 // TODO Auto-generated constructor stub 49 } 50 51 @Override 52 public void display() { 53 // TODO Auto-generated method stub 54 System.out.println(); 55 System.out.print("小鸭"); 56 peformQuack(); 57 performFly(); 58 } 59 60 } 61 62 63 64 package StrategyPattern; 65 66 public class OldDuck extends Duck { 67 68 public OldDuck(FlyBehaviour fly, QuackBehaviour quack) { 69 super(fly, quack); 70 // TODO Auto-generated constructor stub 71 } 72 73 @Override 74 public void display() { 75 // TODO Auto-generated method stub 76 System.out.println(); 77 System.out.print("老鸭"); 78 peformQuack(); 79 performFly(); 80 } 81 82 } 83 84 85 86 87 package StrategyPattern; 88 89 public class RubbDuck extends Duck { 90 91 public RubbDuck(FlyBehaviour fly, QuackBehaviour quack) { 92 super(fly, quack); 93 // TODO Auto-generated constructor stub 94 } 95 96 @Override 97 public void display() { 98 // TODO Auto-generated method stub 99 System.out.println(); 100 System.out.print("橡皮鸭"); 101 peformQuack(); 102 performFly(); 103 } 104 105 }
最后,看看效果吧:
1 public static void main(String[] args) { 2 // TODO Auto-generated method stub 3 Duck littleDuck = new LittleDuck(new CantFly(), new NoQuack()); 4 Duck oldDuck = new OldDuck(new CanFly(), new GagaQuack()); 5 Duck rubbDuck = new RubbDuck(new CantFly(), new ZhizhiQuack()); 6 littleDuck.display(); 7 oldDuck.display(); 8 rubbDuck.display(); 9 }
运行结果:
小鸭不会叫不会飞
老鸭嘎嘎叫会飞
橡皮鸭吱吱叫不会飞