策略模式
基本介绍
-
策略模式(Strategy Pattern)中,定义算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
-
这算法体现了几个设计原则。
第一 把变化的代码从不变的代码中分离出来
第二 针对接口编程而不是具体类(定义了策略接口
第三 多用组合/聚合,少用继承(客户通过组合方式使用策略)。
策略模式就是通过组合的方式将类的一些方法组合起来,每个类都可以持有不同的策略。通过持有不同的策略来达到同样方法不同执行方式的效果。
context就是用来存放策略。
实例演示
现假设要实现一个RPG游戏,该游戏有以下人物:皇帝(King), 皇后(Queen), 骑士(Knight),士兵(Pawn)。
人物可以使用魔法(MagicBehavior)和武器攻击(WeaponBehavior)两种:
这里假设魔法有火球(Fireball Magic, 国王使用), 雷电(Thunder Magic,皇后使用), 回复(Recovery Magic,骑士使用), 冲锋(Assult Magic, 士兵使用)。
武器攻击时,皇帝使用剑(Sword), 皇后使用杖(Stick), 骑士使用枪(Spear), 士兵使用斧头(Axe)。
1)UML类图
2)编写策略接口
这里根据题目有对于每一个角色(context)都有两种策略(strategy),分别是魔法和物理攻击。
public interface WeaponBehavior {
public void attackByWeapon();
}
public interface MagicBehavior{
public void attackByMagic();
}
3)编写不同的策略
对于每种策略都有不同的实现。
这里以魔法中的火球和物理中的剑为例。
public class FireballMagic implements MagicBehavior{
@Override
public void attackByMagic() {
System.out.println("使用火球魔法");
}
}
public class Sword implements WeaponBehavior{
@Override
public void attackByWeapon() {
System.out.println("使用武器-剑攻击");
}
}
4)编写策略持有类
对于本题中每一个角色就是context。本题中的所有角色都是通过聚合的方式来获取策略。
这里以King为例。
public class King implements Role{
private MagicBehavior magicBehavior;
private WeaponBehavior weaponBehavior;
public King(MagicBehavior magicBehavior, WeaponBehavior weaponBehavior) {
this.magicBehavior = magicBehavior;
this.weaponBehavior = weaponBehavior;
}
@Override
public void useMagic() {
magicBehavior.attackByMagic();
}
@Override
public void useWeapon() {
weaponBehavior.attackByWeapon();
}
}
5)测试
public class Client {
public static void main(String[] args) {
King king = new King(new FireballMagic(), new Sword());
king.useMagic();
king.useWeapon();
}
}
策略模式在JDK - Arrays 应用的源码分析
在Arrays中的sort方法就使用了策略模式,通过传入不同策略(排序规则),来执行sort方法。
有两种传入策略的方式,一种是先写好策略(创建Comparator类中的compare方法,然后将实例化的类传入到sort方法参数中,就可以接收排序策略。)
另一种是直接在Arrays.sort()方法中第二个策略参数上直接用lambda(因为这个策略本身就是一个函数式接口