Java 设计模式西游篇 - 第三回:策略模式换法宝 三打白骨精变招

诗曰:

复制代码
妖魔变化多端术,算法切换需灵活。
策略模式来相助,换招如换刀。

📖 故事

师徒四人来到"算法变换山",阴风阵阵,妖气冲天。

唐僧道:"悟空,此山妖气甚重,你要小心。"

悟空笑道:"师父放心,徒儿省得。"

话音未落,只见一女子袅袅而来,手提竹篮。

八戒眼睛都直了:"女菩萨!这是给咱们送饭的!"

悟空火眼金睛一扫,喝道:"妖怪!休得猖狂!"

🐉 踩坑打怪:白骨精的三重变化

第一变:村姑形态

白骨精化作村姑,使出一招"温柔陷阱"!

java 复制代码
// 没有策略模式前,悟空是这样打的
public class Wukong {
    public void fight(BoneDemon demon) {
        if (demon.getForm() == "village_girl") {
            // 打村姑的招式
            System.out.println("金箍棒 - 村姑打击!");
        } else if (demon.getForm() == "old_woman") {
            // 打老妇的招式
            System.out.println("金箍棒 - 老妇打击!");
        } else if (demon.getForm() == "old_man") {
            // 打老翁的招式
            System.out.println("金箍棒 - 老翁打击!");
        }
        // 每多一种形态,就要加一个 if...
    }
}

悟空吐槽: "这代码太丑了!每多一种妖怪形态,俺老孙就要加一个 if!"

一棒子打下,村姑倒地。

第二变:老妇形态

白骨精不死心,又化作老妇,使出一招"苦肉计"!

唐僧果然上当:"悟空!你怎敢滥杀无辜!"

悟空急道:"师父!那是妖怪!"

八戒插话: "猴哥,你这 if-else 太乱了,要是妖怪有十种变化,你不得写十个 if?"

悟空点头:"正是!俺老孙得想个法子!"

第三变:老翁形态

白骨精再变老翁,这次悟空已经想好对策!

悟空喝道: "妖怪!任你有千般变化,俺老孙自有万般应对!看俺的策略模式!"

⚔️ 策略模式大法

第一步:定义策略接口
java 复制代码
// 攻击策略接口
public interface AttackStrategy {
    void attack();
}
第二步:实现各种策略
java 复制代码
// 打村姑的策略
public class VillageGirlAttack implements AttackStrategy {
    @Override
    public void attack() {
        System.out.println("金箍棒 - 村姑打击!轻轻一击,不伤无辜!");
    }
}

// 打老妇的策略
public class OldWomanAttack implements AttackStrategy {
    @Override
    public void attack() {
        System.out.println("金箍棒 - 老妇打击!加大力度!");
    }
}

// 打老翁的策略
public class OldManAttack implements AttackStrategy {
    @Override
    public void attack() {
        System.out.println("金箍棒 - 老翁打击!全力一击!");
    }
}

// 打原形的策略
public class TrueFormAttack implements AttackStrategy {
    @Override
    public void attack() {
        System.out.println("金箍棒 - 原形打击!一棒毙命!");
    }
}
第三步:悟空使用策略
java 复制代码
public class Wukong {
    private AttackStrategy attackStrategy;
    
    // 随时切换策略
    public void setAttackStrategy(AttackStrategy strategy) {
        this.attackStrategy = strategy;
    }
    
    public void fight(BoneDemon demon) {
        System.out.println("悟空:妖怪看棒!");
        attackStrategy.attack();
    }
}

// 实战
Wukong wukong = new Wukong();

// 第一变:村姑
wukong.setAttackStrategy(new VillageGirlAttack());
wukong.fight(demon);

// 第二变:老妇
wukong.setAttackStrategy(new OldWomanAttack());
wukong.fight(demon);

// 第三变:老翁
wukong.setAttackStrategy(new OldManAttack());
wukong.fight(demon);

// 现原形:白骨精
wukong.setAttackStrategy(new TrueFormAttack());
wukong.fight(demon);

🏆 战斗总结

八戒惊叹: "猴哥!你这招高明!不管妖怪怎么变,你换个策略就行,不用改代码!"

悟空得意: "正是!这就是策略模式的妙处------算法自由切换,代码不用修改!"

唐僧总结: "悟空,你这策略模式,可是符合了'开闭原则'?"

悟空答: "师父明鉴!对扩展开放(加新策略不用改现有代码),对修改封闭(不用改 Wukong 类)!"

策略模式的变体

配合工厂使用
java 复制代码
public class StrategyFactory {
    public static AttackStrategy getStrategy(String demonForm) {
        switch (demonForm) {
            case "village_girl":
                return new VillageGirlAttack();
            case "old_woman":
                return new OldWomanAttack();
            case "old_man":
                return new OldManAttack();
            default:
                return new TrueFormAttack();
        }
    }
}

// 使用更简单
wukong.setAttackStrategy(StrategyFactory.getStrategy(demon.getForm()));
wukong.fight(demon);
配合枚举使用
java 复制代码
public enum AttackType {
    VILLAGE_GIRL(new VillageGirlAttack()),
    OLD_WOMAN(new OldWomanAttack()),
    OLD_MAN(new OldManAttack()),
    TRUE_FORM(new TrueFormAttack());
    
    private final AttackStrategy strategy;
    
    AttackType(AttackStrategy strategy) {
        this.strategy = strategy;
    }
    
    public AttackStrategy getStrategy() {
        return strategy;
    }
}

// 使用
wukong.setAttackStrategy(AttackType.TRUE_FORM.getStrategy());

本章要点

要点 说明
核心思想 定义一系列算法,让它们可以互相替换
适用场景 多种算法可切换、避免大量 if-else
优点 符合开闭原则、算法自由切换
缺点 客户端要知道所有策略、策略类增多

下回预告

话说师徒继续西行,来到"消息传递岭"。唐僧要联系如来佛祖,却无音讯。悟空如何施展"观察者模式",让千里眼顺风耳现世?

欲知后事如何,且听第四回分解!


相关推荐
wellc31 分钟前
SpringBoot集成Flowable
java·spring boot·后端
Hui Baby1 小时前
springAi+MCP三种
java
hsjcjh1 小时前
【MySQL】C# 连接MySQL
java
敖正炀1 小时前
LinkedBlockingDeque详解
java
wangyadong3171 小时前
datagrip 链接mysql 报错
java
untE EADO1 小时前
Tomcat的server.xml配置详解
xml·java·tomcat
ictI CABL2 小时前
Tomcat 乱码问题彻底解决
java·tomcat
敖正炀2 小时前
DelayQueue 详解
java
敖正炀2 小时前
PriorityBlockingQueue 详解
java
shark22222222 小时前
Spring 的三种注入方式?
java·数据库·spring