- 模式定义
定义了算法族,分别封装起来,让它们之间可以互相替换,此模式的变化独立于算法的使用者。
- 优点
1.可以将算法的实现细节与使用它的代码隔离开来。
2.符合开闭原则
- 应用场景
1.当你有很多类似的类,但它们执行某些行为的方式不同时,请使用此策略。
2.使用该模式将类的业务逻辑与算法的实现细节隔离开来,这些算法在逻辑上下文中可能不那么重要。
3.当你的类具有大量的条件运算符,并且在同一算法的不同变体之间切换时,请使用此模式。
- 举例:
比如说我们开发一个植物大战僵尸,最开始只有普通僵尸和旗手僵尸,我们将其共有的属性和方法封装为一个抽象的父类,代码如下:
public class ZombieTest { public static void main(String[] args) { AbstractZombie normalZombie = new NormalZombie(); AbstractZombie flagZombie = new FlagZombie(); normalZombie.display(); normalZombie.move(); normalZombie.attack(); System.out.println("-------------------"); flagZombie.display(); flagZombie.move(); flagZombie.attack(); } } abstract class AbstractZombie{ public abstract void display(); public void attack(){ System.out.println("咬。。"); } public void move(){ System.out.println("一步一步移动。。。"); } } class NormalZombie extends AbstractZombie{ @Override public void display() { System.out.println("我是普通僵尸。。。"); } } class FlagZombie extends AbstractZombie{ @Override public void display() { System.out.println("我是旗手僵尸"); } }
这个时候我们在添加一个大头僵尸,其攻击方式是头撞,这时候我们只需要继承父类并重写display和attack方法即可,
class BigHeadZombie extends AbstractZombie{ @Override public void display() { System.out.println("我是大头僵尸"); } @Override public void attack() { System.out.println("头撞"); } }
如果我们再要开发一个跳舞僵尸,其攻击方式也是头撞,单他的移动方式是跳舞移动,那我们可以直接继承大头僵尸重写move方法即可。
但是这也引申出一个问题,如果我们在开发一个舞王僵尸,他的移动方式是跳舞,但是攻击方式是挠的话,我们按照上述方式的做法应该是继承跳舞僵尸并重写attack方法。
这种方式会显得我们的继承关系无比长,不易于我们的开发维护。这个时候就可以使用策略模式。
public class StrategyTest { public static void main(String[] args) { Zombie normalZombie = new NormalZombie(); normalZombie.display(); normalZombie.move(); normalZombie.attack(); normalZombie.setAttackable(new HeadAttack()); normalZombie.attack(); } } interface Moveable{ void move(); } interface Attackable{ void attack(); } abstract class Zombie{ abstract public void display(); Moveable moveable; Attackable attackable; abstract void move(); abstract void attack(); public Zombie(Moveable moveable, Attackable attackable) { this.moveable = moveable; this.attackable = attackable; } public Moveable getMoveable() { return moveable; } public void setMoveable(Moveable moveable) { this.moveable = moveable; } public Attackable getAttackable() { return attackable; } public void setAttackable(Attackable attackable) { this.attackable = attackable; } } class StepByStepMove implements Moveable{ @Override public void move() { System.out.println("一步一步移动"); } } class BiteAttack implements Attackable{ @Override public void attack() { System.out.println("咬"); } } class HeadAttack implements Attackable{ @Override public void attack() { System.out.println("头撞"); } } class NormalZombie extends Zombie{ public NormalZombie(){ super(new StepByStepMove(),new BiteAttack()); } public NormalZombie(Moveable moveable, Attackable attackable) { super(moveable, attackable); } @Override public void display() { System.out.println("我是普通僵尸"); } @Override void move() { moveable.move(); } @Override void attack() { attackable.attack(); } } class FlagZombie extends Zombie{ public FlagZombie(){ super(new StepByStepMove(),new BiteAttack()); } public FlagZombie(Moveable moveable, Attackable attackable) { super(moveable, attackable); } @Override public void display() { System.out.println("我是旗手僵尸"); } @Override void move() { moveable.move(); } @Override void attack() { attackable.attack(); } }
普通僵尸本来attack是“咬”,我们重新设置他的攻击策略,他的攻击方式就变成了头撞,在实现策略时可以随意通过set不同的策略来达到不同的效果
- Spring &JDK 源码中的应用
java.util.Comparator
org.springframework.beans.factory.support.InstantiationStrategy