当前位置: 首页
业界动态
别再死记设计模式了!Java 21+ 把 Strategy Pattern 玩出花,这才是现代写法

别再死记设计模式了!Java 21+ 把 Strategy Pattern 玩出花,这才是现代写法

热心网友 时间:2026-04-28
转载

Strategy Pattern 从来没变,变的是 Ja va。从“类爆炸”到“函数式”,再到“类型驱动 + 模式匹配”,它已经从一种设计技巧,进化成了一种语言能力。

你写的不是设计模式,是“文件工厂”

还记得早期写策略模式的那种体验吗?

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

先定义一个接口,然后跟着N个实现类。需求但凡有点风吹草动,类文件的数量就跟着水涨船高。五种策略?那就意味着五个类文件。想加点校验逻辑?得,五个文件都得改一遍。

从纯粹的设计角度看,这确实叫“优雅解耦”;但切换到工程实践的视角,这感觉更像是——一个高效的“文件膨胀器”。

如果今天还在沿用这套写法,那你的代码风格,可能还停留在Ja va 7的时代。

别再只会“接口 + N个实现类”的老套路

不妨先回顾一下最经典、最传统的写法。

public interface PaymentStrategy {
    void pay(double amount);
}
public class CreditCardPayment implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " using Credit Card");
    }
}
public class PayPalPayment implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " using PayPal");
    }
}

调用端通常是这样的:

public class PaymentService {
    private PaymentStrategy strategy;
    public PaymentService(PaymentStrategy strategy) {
        this.strategy = strategy;
    }
    public void process(double amount) {
        strategy.pay(amount);
    }
}

平心而论,这套写法本身没有错,它完美体现了面向接口编程的思想。但问题也显而易见:

  • 类爆炸:策略数量与类文件数量线性增长。
  • 修改成本高:任何公共逻辑的调整都可能需要修改多个文件。
  • 逻辑分散:相同领域的逻辑散落在各个类中,难以形成整体视图。
  • 可读性下降:随着策略增多,在代码库中定位和理解具体逻辑变得越来越困难。

别再只会用 Ja va 8 Lambda 的“半升级版本”

Ja va 8引入Lambda表达式后,很多人觉得已经迈向了“现代化”:

PaymentStrategy creditCard = amount ->
        System.out.println("Paid " + amount + " using Credit Card");
PaymentStrategy paypal = amount ->
        System.out.println("Paid " + amount + " using PayPal");

看起来确实清爽了不少,至少文件数量降下来了。但深究下去,核心问题依然存在:

  • 没有类型约束:策略本质上还是一个函数对象,缺乏丰富的类型信息。
  • 复杂逻辑难维护:当策略逻辑变得复杂时,内联的Lambda会变得臃肿且难以测试。
  • 扩展性依旧有限:增加新的策略类型,仍然需要手动修改调用处的逻辑。

可以说,这只是利用新语法做了“文件减肥”,并没有触及策略模式“模型”的升级。

别再忽略 Ja va 17 的 sealed + record 带来的结构升级

真正的转折点,其实是从Ja va 17开始的。sealed classes/interfaces和record这两个特性,为我们重新构思策略模式提供了全新的建筑材料。

我们可以用sealed interface来严格限定策略的家族成员,用record来清晰表达策略所携带的数据结构。

// 定义策略的密封接口,明确声明允许的实现
package com.icoderoad.strategy;
public sealed interface PaymentStrategy
        permits CreditCard, PayPal {}

// 策略一:信用卡支付,用record封装卡号数据
package com.icoderoad.strategy;
public record CreditCard(String cardNumber) implements PaymentStrategy {}

// 策略二:PayPal支付,用record封装邮箱数据
package com.icoderoad.strategy;
public record PayPal(String email) implements PaymentStrategy {}

这样一来,策略不再仅仅是封装一个“行为”的抽象,而是进化为“数据 + 类型”的强组合。每种策略是什么,能携带什么数据,在编译期就一清二楚。

别再写 if-else,Ja va 21 的 pattern matching 才是核心玩法

到了Ja va 21,随着模式匹配for switch的成熟,策略模式终于完成了它的终极进化。处理逻辑可以变得如此集中和直观:

package com.icoderoad.strategy;
public class PaymentProcessor {
    public static void process(PaymentStrategy strategy, double amount) {
        switch (strategy) {
            case CreditCard cc ->
                 System.out.println("Paid " + amount + " with card: " + cc.cardNumber());
            case PayPal pp ->
                 System.out.println("Paid " + amount + " via PayPal: " + pp.email());
        }
    }
}

这种写法带来的变化是本质性的:

  • 不再需要N个类分散逻辑:所有策略的分支处理集中在一处,一目了然。
  • 所有策略集中在一个可控范围:阅读和维护者无需在多个文件间跳转。
  • 编译期保证类型安全:switch表达式会检查是否覆盖了所有sealed接口的许可类型。
  • 代码结构更加线性、可读:逻辑流是线性的,极大地降低了认知负担。

别再把策略模式当“类设计”,它本质是“分支控制”

这里存在一个普遍的误解。策略模式的核心目的,从来不是为了展示多态技巧,它的本质是:

在运行时选择不同逻辑路径

现代Ja va语法给了我们更直接、更声明式的方式来表达这一意图:

public static void process(PaymentStrategy strategy, double amount) {
    switch (strategy) {
        case CreditCard cc -> handleCard(cc, amount);
        case PayPal pp -> handlePayPal(pp, amount);
    }
}

对比旧时代的写法,优势立现:

  • 少了类跳转:无需在多个实现类中寻找逻辑。
  • 少了思维负担:逻辑脉络集中,上下文清晰。
  • 多了编译期校验:编译器帮你确保处理了所有已知策略,避免遗漏。

用一张流程图看清新旧策略模式差异

图片

别再担心扩展性,现代写法反而更安全

肯定有人会质疑:把所有逻辑写在一个switch里,是不是违反了开闭原则?新增策略不是还得修改这个switch吗?

其实,情况正好相反。这种现代写法在大型或严谨的系统中,反而提供了更强的安全性。

传统模式的问题:

  • 新增策略:需要新增类,并且必须在代码的某个地方(可能是工厂或配置)修改调用逻辑来纳入这个新类。
  • 逻辑分散风险:相关逻辑分散在各处,容易在修改时产生不一致。

现代模式的优势:

  • sealed 限制策略范围:策略类型是封闭的、已知的,防止不可控的扩展。
  • switch 强制覆盖所有分支:如果新增一个策略类型(如Alipay)但没有在switch中处理,编译器会直接报错,这杜绝了运行时遗漏。
  • 修改集中,可控性更高:所有策略的逻辑入口明确且唯一,便于审计和管控。

什么时候该用“现代策略模式”?

这种基于密封类型和模式匹配的现代策略模式,并非银弹,它有自己最适合的战场:

适用场景:

  • 策略数量相对有限且稳定,例如支付方式、订单状态机、通知渠道等。
  • 策略逻辑需要集中管理和审视,强调可读性与可维护性。
  • 对类型的严谨性有高要求,希望借助编译器来保证逻辑完整性。

不适用场景:

  • 策略需要高度动态加载,如插件化系统。
  • 策略完全由第三方提供,其类型不可在编译期预知。

设计模式不会过时,但写法一定会

说到底,策略模式的思想内核从未改变,变化的是Ja va这门语言本身。它从最初导致“类爆炸”的经典实现,演进到利用Lambda的“函数式”简化,再到如今“类型驱动 + 模式匹配”的声明式表达。策略模式,已经从一种需要刻意套用的“设计技巧”,进化成了语言原生支持的“表达能力”。

真正的高手,或许不在于能背诵多少种设计模式,而在于懂得审时度势——知道在语言进化的新阶段,何时该放下过去的经典实现,用更现代、更贴合语言特性的方式,将同样的思想重写一遍。

来源:https://www.51cto.com/article/841438.html

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
RPA与AI:区别、联系与实在Agent的融合创新之道

RPA与AI:区别、联系与实在Agent的融合创新之道

在企业数字化转型的浪潮中,传统的机器人流程自动化(RPA)曾经是提升效率的关键一步。然而,技术不会原地踏步。如今,一个更强大的进化形态已经出现——那就是深度融合了AI智能与RPA执行力的新一代智能体产品,例如实在Agent。它彻底超越了简单的自动化,开创了“智能流程自动化”的新范式。那么,RPA和A

时间:2026-04-28 12:45
亚马逊VC和SC区别是什么?一篇给你讲清楚

亚马逊VC和SC区别是什么?一篇给你讲清楚

很多卖家刚接触亚马逊时,都会对两个词犯迷糊:VC和SC。它们听起来有点像,但背后的玩法完全不同,选错了可能直接影响到生意的节奏和利润。 今天咱们就掰开揉碎,聊聊亚马逊的供应商中心(Vendor Central, VC)和卖家中心(Seller Central, SC)到底有什么区别,帮你找到最适合自

时间:2026-04-28 12:44
亚马逊FBA仓储费用怎么收费?算清这笔账,轻松省下不少钱

亚马逊FBA仓储费用怎么收费?算清这笔账,轻松省下不少钱

做亚马逊,使用FBA(亚马逊物流)几乎是卖家们的标准操作,它能显著提升物流体验,是抢占购物车的关键。但谈到FBA,最令人头疼的莫过于那笔计算复杂且时常变动的仓储费用了。如果管理不善,这笔开支足以悄悄侵蚀掉大部分利润。今天,我们就来彻底厘清FBA仓储费,从计费逻辑到行之有效的省钱策略,为你提供一套清晰

时间:2026-04-28 12:44
亚马逊招商链接多久下来?

亚马逊招商链接多久下来?

一、招商链接审核流程与时效:为什么有人快有人慢? 想在亚马逊上开店,第一步拿到官方招商链接往往就成了“拦路虎”。不少卖家满怀期待地提交了申请,结果却石沉大海,只能干等。“到底要等多久?”这种不确定性,确实挺磨人的。 其实,招商链接的发放并非简单的自动化流程,它背后有一套清晰的审核逻辑,受多种因素牵制

时间:2026-04-28 12:44
RPA物流跟踪快吗?自动化工具高效实践盘点

RPA物流跟踪快吗?自动化工具高效实践盘点

下午三点,跨境电商物流的“日常战役” 下午三点,某跨境电商物流经理小王正对着电脑屏幕上一字排开的十几个浏览器标签页发愁。每个标签页都对应一家不同的快递公司跟踪网站。他的任务,是把上百个物流单号逐一复制、粘贴、查询、记录状态,最后整理成一份汇总表格发给客户。一个不留神,两个单号的状态登记错了,客户投诉

时间:2026-04-28 12:44
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜
热门教程
更多
  • 游戏攻略
  • 安卓教程
  • 苹果教程
  • 电脑教程