定义
定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
通俗点的讲,就是将类中一组经常变化的策略(方法)委托于一组具体策略类,这些策略类之间可以互相替换(共同继承于一个接口),自由选择行为进行组合。
用途
1、对同种行为的复用
2、继承也可以通过重载来实现多种行为,但是这种方式是采取硬编码的,具有一定的强制性,并且难以维护和难以扩展。
3、可以动态的变化行为。
参与对象
- 上下文对象:持有对抽象策略类的引用,还有其他一些不变化的方法和变量。
- 抽象策略对象:通常用接口实现
- 具体策略对象:实现了不同功能的不同算法
举例应用
一个网络游戏中有多种不同的角色,每种角色一次可以使用一个武器,在游戏过程中可以更换武器。
进行抽象
- 上下文对象:不同的角色
- 抽象策略对象:使用武器
- 具体策略对象:使用具体的武器
类图
- Character:不同角色的抽象类
- WeaponBehavior:使用武器这种行为的接口
具体实现
Character:
public class Character {
String name;
WeaponBehavior behavior = new KnifeBehavior();
public Character(String name) {
this.name = name;
}
public void fight(){
System.out.print(name+":");
behavior.userWeapon();
}
public void setBehavior(WeaponBehavior behavior) {
this.behavior = behavior;
}
}
具体角色:
public class King extends Character {
public King(String name) {
super(name);
}
}
public class Queen extends Character {
public Queen(String name) {
super(name);
}
}
public class Knight extends Character {
public Knight(String name) {
super(name);
}
}
使用武器接口:
public interface WeaponBehavior {
void userWeapon();
}
具体实现:
public class SwordBehavior implements WeaponBehavior{
@Override
public void userWeapon() {
System.out.println("用宝剑攻击!");
}
}
public class KnifeBehavior implements WeaponBehavior {
@Override
public void userWeapon() {
System.out.println("用匕首攻击!");
}
}
public class BowAndArrowBehavior implements WeaponBehavior {
@Override
public void userWeapon() {
System.out.println("用弓箭射击!");
}
}
public class AxeBehavior implements WeaponBehavior {
@Override
public void userWeapon() {
System.out.println("用斧头砍劈!");
}
}
使用:
public class Main {
public static void main(String[] args) {
King king = new King("King 1");
king.setBehavior(new SwordBehavior());
king.fight();
king.setBehavior(new KnifeBehavior());
king.fight();
}
}
Console:
King 1:用宝剑攻击!
King 1:用匕首攻击!
Process finished with exit code 0
通过案例就可以发现,使用武器这种行为的具体实现不是由角色本身实现,而委托于WeaponBehavior的具体实现类(这种面向接口编程的方式可以灵活的扩展),可以动态的选择对应的策略适应不同的场景。
总结:
1、找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
如果例子中,经常变化的fight()行为不委托于WeaponBehavior实现,那么就很难维护,修改的时候需要修改很多处。
2、针对接口编程,而不是针对实现编程。
使用WeaponBehavior这种接口(抽象类也可以),就能够很好的利用多态的性质,不必知道具体实现,也可以灵活的扩展,增加新的具体行为实现,而不影响原来的实现。
3、多用组合,少用继承
组合具有更好的灵活性,WeaponBehavior采用组合的方式和Character进行结合,可以动态的改变行为,而且也可以隐藏行为的具体实现。