设计模式-策略模式(Strategy Pattern)
本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/
策略模式简述
我们通常需要动态改变一个对象的某种行为,但是并不改变相应的接口,策略模式就可以完成这样的工作。
策略模式的定义与基本结构
定义:策略模式定义了一簇算法,并将每一个算法封装起来,让它们可以互相替换,这样可以让算法的变化独立于使用它的客户端。
(ps:这里的算法二字不用理解的很局限,在后面的例子里我们会细说)
让我们来看一张来自百度百科策略模式图册的结构图。
Context:代表客户类,客户类会包含一个strategy类的实例,并提供一个调用strategy内算法的接口方法用来调用strategy.algorithmInterface(),也就是说Context将算法的实现细节都委托给了strategy的实例类。
Strategy:所有算法的超类,让我们可以面向接口编程而不是某个特定实例。
ConcreteStrategy:具体的算法实例,封装了一个实际的算法,实现了被调用算法的方法algorithmInterface()。
注:context与strategy是has-a的关系
一个简单的实例
让我们来考虑一个这样的问题,我们在玩游戏的时候主角通常都会装备不同的武器来应对不同的敌人,但是我们一般只有一个攻击键,虽然我们每次都按相同的按键,但是当我们装备的武器不同的时候,我们的攻击方式是不同的,装备法杖的时候,我们会发射魔法弹,装备弓箭的时候我们会射出一支利箭,装备板砖的时候,我们对着敌人的脸就是一阵乱乎。
假设我们可以随时切换武器,怎么做到同一个按键按下去会有不同的攻击模式呢?
这里我们就可以利用策略模式,之前我们说过不要对这里所说的"算法"的理解太狭隘,不同的攻击模式也能理解成不同的"算法",套用我们上面的模型我们可以像这样解决问题。
写一个Weapon类当做超类,里面有一个抽象方法attackPattern(),每一个具体的武器(比如法杖)都继承这个超类,并实现这个方法。
然后我们写一个Hero类,里面包含了一个Weapon类的实例,并且有一个方法attack(),这个方法内部会调用Weapon类的attackPattern()方法,所以只要我们动态的改变了Hero里的Weapon实例,当我们调用attack()方法的时候,我们的攻击模式自然就会改变,而这就是策略模式的能力所在,它将attack()的实现细节委托给了Weapon类,而Weapon类是的不同实例里面实现了不同的攻击模式,这样就完成了"让算法的变化独立于使用它的客户端",因为在任何状态下,Hero类只需要调用同一个方法attack(),就可以了。当然为了能改变Hero类的Weapon实例,我们还需要一个setWeapon()方法。
废话不多说,下面给出实例代码。
Weapon类
1 public abstract class Weapon { 2 String name; 3 public abstract void attactPattern(); 4 }
下面给出Weapon的子类,Wand(法杖)和Bow(弓)
1 public class Wand extends Weapon { 2 Wand(){ 3 super(); 4 name="法杖"; 5 } 6 @Override 7 public void attactPattern() { 8 System.out.println("毁天灭地的魔法弹"); 9 } 10 } 11 12 public class Bow extends Weapon { 13 Bow(){ 14 super(); 15 name="弓"; 16 } 17 @Override 18 public void attactPattern() { 19 System.out.println("贯穿苍穹的利箭"); 20 } 21 }
然后我们给出Hero类
1 public class Hero { 2 Hero(Weapon weapon){ 3 this.weapon=weapon; 4 } 5 Weapon weapon; 6 public void setWeapon(Weapon weapon){ 7 this.weapon=weapon; 8 } 9 public void attack(){ 10 System.out.print("勇者使出了一招---"); 11 weapon.attactPattern(); 12 System.out.println("Σ(`д′*ノ)ノ"); 13 } 14 }
最后我们给出测试代码
1 public class Test { 2 public static void main(String[] args) { 3 Hero hero=new Hero(new Wand()); 4 hero.attack(); 5 hero.setWeapon(new Bow()); 6 hero.attack(); 7 } 8 }
输出如下
策略模式到此结束,是不是觉得很简单呢~♪(^∇^*)
参考资料:
1,《Head First 设计模式》