1. 定义

定义了算法族,分别封装起来,让它们之间可以互相替换,此模式的变 化独立于算法的使用者。

2. 案例

植物大战僵尸,僵尸类型有很多种,以后还可能会扩展
第一个版本僵尸:
image.png
image.png
第二个版本僵尸:
image.png
image.png
未完待续,第N个版本僵尸:
image.png

2.1 第一种实现(不推荐)

定义一个普通僵尸,其他僵尸继承它,重写对应方法,但是有的方法可能时公用的,再去继承另外的僵尸并重写方法,会使得类结构图复杂

2.2 第二种实现:策略模式

分别定义僵尸移动、攻击为算法族,封装起来。
封装移动、攻击:

  1. interface Moveable {
  2. void move();
  3. }
  4. interface Attackable {
  5. void attack();
  6. }

实现一个移动

  1. class StepByStepMove implements Moveable {
  2. @Override
  3. public void move() {
  4. System.out.println("一步一步移动.");
  5. }
  6. }

实现两个攻击

  1. class BiteAttack implements Attackable {
  2. @Override
  3. public void attack() {
  4. System.out.println("咬.");
  5. }
  6. }
  7. class HitAttack implements Attackable {
  8. @Override
  9. public void attack() {
  10. System.out.println("打.");
  11. }
  12. }

定义僵尸基类

  1. abstract class Zombie {
  2. abstract public void display();
  3. Moveable moveable;
  4. Attackable attackable;
  5. public Zombie(Moveable moveable, Attackable attackable) {
  6. this.moveable = moveable;
  7. this.attackable = attackable;
  8. }
  9. abstract void move();
  10. abstract void attack();
  11. public Moveable getMoveable() {
  12. return moveable;
  13. }
  14. public void setMoveable(Moveable moveable) {
  15. this.moveable = moveable;
  16. }
  17. public Attackable getAttackable() {
  18. return attackable;
  19. }
  20. public void setAttackable(Attackable attackable) {
  21. this.attackable = attackable;
  22. }
  23. }

定义一个普通僵尸:默认移动为StepByStepMove,默认攻击为BiteAttack

  1. class NormalZombie extends Zombie {
  2. public NormalZombie() {
  3. super(new StepByStepMove(), new BiteAttack());
  4. }
  5. public NormalZombie(Moveable moveable, Attackable attackable) {
  6. super(moveable, attackable);
  7. }
  8. @Override
  9. public void display() {
  10. System.out.println("我是普通僵尸.");
  11. }
  12. @Override
  13. void move() {
  14. moveable.move();
  15. }
  16. @Override
  17. void attack() {
  18. attackable.attack();
  19. }
  20. }

定义一个棋手僵尸:默认移动为StepByStepMove,默认攻击为BiteAttack

  1. class FlagZombie extends Zombie {
  2. public FlagZombie() {
  3. super(new StepByStepMove(), new BiteAttack());
  4. }
  5. public FlagZombie(Moveable moveable, Attackable attackable) {
  6. super(moveable, attackable);
  7. }
  8. @Override
  9. public void display() {
  10. System.out.println("我是旗手僵尸.");
  11. }
  12. @Override
  13. void move() {
  14. moveable.move();
  15. }
  16. @Override
  17. void attack() {
  18. attackable.attack();
  19. }
  20. }

使用:

  1. public class StrategyTest {
  2. public static void main(String[] args) {
  3. Zombie zombie = new NormalZombie();
  4. zombie.display();
  5. zombie.attack();
  6. zombie.move();
  7. //还可以重新设置攻击方式
  8. zombie.setAttackable(new BiteAttack());
  9. zombie.attack();
  10. }
  11. }

3. 应用场景

  1. 当你有很多类似的类,但它们执行某些行为的方式不同时,请使用此 策略。

    1. 使用该模式将类的业务逻辑与算法的实现细节隔离开来,这些算法在 逻辑上下文中可能不那么重要。
  2. 当你的类具有大量的条件运算符,并且在同一算法的不同变体之间切 换时,请使用此模式。

    4. 优点:

  3. 可以将算法的实现细节与使用它的代码隔离开来。

  4. 符合开闭原则

    5. Spring &JDK 源码中的应