设计模式之策略模式

假设接到设计僵尸大战中僵尸角色,当前只有普通僵尸和棋手僵尸
抽象僵尸的公共行为

public abstract class AbstractZombie {
    abstract void display();
    abstract void move();
    abstract void attack();
}

普通僵尸

public class NormalZombie extends AbstractZombie {
    @Override
    void display() {
        System.out.println("普通僵尸");
    }

    @Override
    void move() {
        System.out.println("每次移动一步");
    }

    @Override
    void attack() {
        System.out.println("咬");
    }
}

棋手僵尸

public class FlagZombie extends AbstractZombie {
    @Override
    void display() {
        System.out.println("普通僵尸+旗帜");
    }

    @Override
    void move() {
        System.out.println("每次移动一步");
    }

    @Override
    void attack() {
        System.out.println("咬");
    }
}

测试:

public class StrategyTest {
    public static void main(String[] args) {
        NormalZombie normalZombie = new NormalZombie();
        normalZombie.display();
        normalZombie.move();
        normalZombie.attack();
    }
}

如果此时产品经理说僵尸在吃到豌豆后,需要加快移动或者改变僵尸的显示方式或者攻击的方式,是不是得改动存量代码?很难维护?这种hard coding力不从心。
此时引入策略模式就是很好的选择,将各种行为抽象为一个个接口,并定义一个个具体的行为类(即策略),抽象僵尸包含这些策略接口,具体策略来执行具体的行为。

定义

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

策略模式改造

  • 抽象攻击方式和定义具体的攻击策略
public interface Attack {
    void attack();
}

public class BiteAttack implements Attack {
    @Override
    public void attack() {
        System.out.println("攻击方式:咬");
    }
}

public class HeadAttack implements Attack {
    @Override
    public void attack() {
        System.out.println("攻击方式:头撞击");
    }
}
  • 抽象移动方式和定义具体的移动策略
public interface Attack {
    void attack();
}

public class OneStepMovable implements Movable {
    @Override
    public void move() {
        System.out.println("每次移动一步");
    }
}

public class TwoStepMovable implements Movable {
    @Override
    public void move() {
        System.out.println("每次移动两步");
    }
}
  • 改造抽象僵尸
public abstract class AbstractZombie {
    Movable movable;
    Attack attack;

    AbstractZombie() {
        this(new OneStepMovable(), new BiteAttack());
    }

    AbstractZombie(Movable movable, Attack attack) {
        this.movable = movable;
        this.attack = attack;
    }

    public void setMovable(Movable movable) {
        this.movable = movable;
    }

    public void setAttack(Attack attack) {
        this.attack = attack;
    }

    abstract void display();

    abstract void move();

    abstract void attack();
}
  • 测试
public class StrategyTest {
    public static void main(String[] args) {
        NormalZombie normalZombie = new NormalZombie();
        normalZombie.display();
        normalZombie.move();
        normalZombie.attack();
        // 使僵尸在运行过程中动态修改移动方式和攻击方式
        normalZombie.setMovable(new TwoStepMovable());
        normalZombie.move();
        normalZombie.setAttack(new HeadAttack());
        normalZombie.attack();
    }
}

应用场景

  • 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。
  • 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。
  • 对客户隐藏具体策略(算法)的实现细节,彼此完全独立。

源码级应用

  • Spring源码
    策略接口:org.springframework.beans.factory.support.InstantiationStrategy
    具体策略:CglibSubclassingInstantiationStrategy和SimpleInstantiationStrategy
    该策略表示在Spring框架中AbstractAutowireCapableBeanFactory使用哪种方式实例化bean对象;第一种是cglib代理创建对象,第二种是通过普通的newInstance创建实例。

  • JDK源码
    策略接口:java.util.Comparator
    Comparator应用非常广泛,有很多策略实现。例如:Spring实现的OrderComparator,用来实现排序的,等等
    也可自定义实现:

public class MyComparator implements Comparator<Integer> {

    @Override
    public int compare(Integer o1, Integer o2) {
        return o1.compareTo(o2);
    }

	public static void main(String[] args) {
		// 	比较两个数的大小
        Integer i1 = 1;
        Integer i2 = 2;
        MyComparator comparator = new MyComparator();
        System.out.println(comparator.compare(i1, i2) < 0);
    }
}

相关推荐

  1. 设计模式策略模式

    2024-04-01 13:22:01       30 阅读
  2. 设计模式策略模式

    2024-04-01 13:22:01       33 阅读
  3. 设计模式策略模式

    2024-04-01 13:22:01       18 阅读
  4. 设计模式策略模式

    2024-04-01 13:22:01       15 阅读
  5. 设计模式策略模式

    2024-04-01 13:22:01       12 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-01 13:22:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-01 13:22:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-01 13:22:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-01 13:22:01       20 阅读

热门阅读

  1. Spark数据倾斜解决方案

    2024-04-01 13:22:01       19 阅读
  2. 如何用Redis实现消息队列

    2024-04-01 13:22:01       23 阅读
  3. Codeforces Round 932 (Div. 2)(A,B,C,D)

    2024-04-01 13:22:01       18 阅读
  4. [蓝桥杯 2016 国 C] 赢球票

    2024-04-01 13:22:01       19 阅读
  5. 专升本-大数据

    2024-04-01 13:22:01       20 阅读
  6. 银联扫码接口开通流程及注意事项

    2024-04-01 13:22:01       23 阅读
  7. 【Spring】通过Spring收集自定义注解标识的方法

    2024-04-01 13:22:01       18 阅读
  8. 03-28 周四 Linux 并行工具使用xargs和parallel

    2024-04-01 13:22:01       20 阅读
  9. 装饰器模式:灵活增强功能的利器

    2024-04-01 13:22:01       16 阅读
  10. 手机投屏到电脑

    2024-04-01 13:22:01       18 阅读