当前位置: 首页 > news >正文

【Java学习】【Java基础】--第3篇:初学模板方法模式和策略模式

一、模板方法模式 (Template Method Pattern)

1. 核心思想:骨架不变,细节可变

2. 模板方法模式的关键特点

  1. 控制流程:父类控制算法骨架,子类实现具体步骤
  2. 代码复用:公共代码在抽象类中实现
  3. 扩展性:通过钩子方法提供灵活性
  4. 好莱坞原则:"不要调用我们,我们会调用你" - 子类不直接调用父类,而是父类调用子类(父类决定了流程,子类决定了细节)

假设要开一家饮品店,制作饮料有固定的流程,但具体步骤可以调整。

3. 模式结构

// 抽象类 - 定义饮料制作模板
abstract class BeverageTemplate {// 模板方法 - final防止子类改变算法骨架public final void prepareBeverage() {boilWater();brew();pourInCup();if (customerWantsCondiments()) {addCondiments();}serve();}// 固定步骤,子类共享private void boilWater() {System.out.println("烧开水");}private void pourInCup() {System.out.println("倒入杯中");}private void serve() {System.out.println("端给顾客");}// 抽象方法 - 由子类实现具体细节protected abstract void brew();protected abstract void addCondiments();// 钩子方法,子类可以选择重写protected boolean customerWantsCondiments() {return true; // 默认加调料}
}

4. 具体实现

// 咖啡具体实现
class Coffee extends BeverageTemplate {@Overrideprotected void brew() {System.out.println("冲泡咖啡");}@Overrideprotected void addCondiments() {System.out.println("添加糖和牛奶");}@Overrideprotected boolean customerWantsCondiments() {// 模拟部分顾客需要添加调料return Math.random() > 0.5;}
}// 茶具体实现
class Tea extends BeverageTemplate {@Overrideprotected void brew() {System.out.println("浸泡茶叶");}@Overrideprotected void addCondiments() {System.out.println("添加柠檬");}
}public class Main {public static void main(String[] args) {System.out.println("制作咖啡");Coffee coffee = new Coffee();coffee.prepareBeverage();// 制作咖啡// 烧开水// 冲泡咖啡// 倒入杯中// 添加糖和牛奶// 端给顾客System.out.println();System.out.println("制作茶饮");Tea tea = new Tea();tea.prepareBeverage();// 制作茶饮// 烧开水// 浸泡茶叶// 倒入杯中// 添加柠檬//端给顾客}
}

二、策略模式 (Strategy Pattern)

1. 核心思想:定义算法家族,让它们可以互相替换

2. 策略模式的关键特点

  1. 开闭原则:无需修改上下文即可引入新策略
  2. 消除条件语句:用多态代替复杂的条件判断
  3. 代码复用:可以在不同上下文中复用一个策略
  4. 灵活性:运行时动态切换算法
  5. 单一职责:每个算法都有自己的类

假设要实现一个支付系统,支持多种支付方式,每种支付方式的算法不同。

3. 模式结构

// 策略接口 - 定义所有支付方式的共同行为
interface PaymentStrategy {void pay(double amount);boolean validate();
}// 具体实现 - 信用卡支付
class CreditCardPayment implements PaymentStrategy {// 信用卡号private String cardNumber;public CreditCardPayment(String cardNumber) {this.cardNumber = cardNumber;}@Overridepublic void pay(double amount) {System.out.println("使用信用卡支付" + amount + "元");System.out.println("卡号: ****-****-****-" + maskCardNumber());}@Overridepublic boolean validate() {return cardNumber != null && cardNumber.length() == 16;}private String maskCardNumber() {return cardNumber.substring(12);}
}// 具体实现 - 支付宝支付
class AlipayPayment implements PaymentStrategy {private String account;public AlipayPayment(String account) {this.account = account;}@Overridepublic void pay(double amount) {System.out.println("使用支付宝支付" + amount + "元");System.out.println("账户: " + account);}@Overridepublic boolean validate() {return account != null && account.contains("@");}
}

4. 上下文类 - 使用策略:

// 支付上下文 - 负责使用策略
class PaymentContext {private PaymentStrategy paymentStrategy;private String orderId;public PaymentContext(String orderId) {this.orderId = orderId;}// 设置策略public void setPaymentStrategy(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}// 执行支付public boolean executePayment(double amount) {if (paymentStrategy == null) {System.out.println("请设置支付模式!");return false;}if (!paymentStrategy.validate()) {System.out.println("验证失败!");return false;}System.out.println("开始处理订单" + orderId);paymentStrategy.pay(amount);System.out.println("支付成功");return true;}
}public class Main {public static void main(String[] args) {String orderId = "ABC_12345";PaymentContext paymentContext = new PaymentContext(orderId);// 使用信用卡策略System.out.println("===使用信用卡支付===");paymentContext.setPaymentStrategy(new CreditCardPayment("1234567891011121"));paymentContext.executePayment(100.0);// ===使用信用卡支付===// 开始处理订单ABC_12345// 使用信用卡支付100.0元// 卡号: ****-****-****-1121// 支付成功// 使用支付宝策略System.out.println("\n===使用支付宝支付===");paymentContext.setPaymentStrategy(new AlipayPayment("user@alipay.com"));paymentContext.executePayment(25.0);// ===使用支付宝支付===// 开始处理订单ABC_12345// 使用支付宝支付25.0元// 账户: user@alipay.com// 支付成功}
}

三、深入对比分析

1. 设计目标不同

方面 模板方法模式 策略模式
关注点 算法步骤的固定与变化 算法实现的互换性
关系 父子类继承关系 接口与实现关系
控制权 父类控制流程 客户端控制选择

2. 代码结构对比

模板方法模式:

abstract class Processor {public final void process() {  // 固定流程step1();step2();  // 抽象方法step3();}private void step1() { /* 实现 */ }protected abstract void step2();private void step3() { /* 实现 */ }
}

策略模式:

interface Strategy {void execute();
}class Context {private Strategy strategy;public void setStrategy(Strategy s) { this.strategy = s; }public void execute() { strategy.execute();  // 委托给策略}
}

四、两者结合

模板方法模式定义数据处理框架

abstract class DataProcessor {// 父类决定流程public final void process(String input) {if (!validateInput(input)) {System.out.println("输入不得为空!");return;}String data = transformData(input);outResult(data);}// 抽象方法 - 子类具体实现数据转换protected abstract String transformData(String input);private boolean validateInput(String input) {return input != null && !input.trim().isEmpty();}private void outResult(String data) {System.out.println("输出:" + data);}}

策略模式提供不同的转换实现

interface TransformStrategy {String transform(String input);
}class UppercaseStrategy implements TransformStrategy {@Overridepublic String transform(String input) {return input.toUpperCase();}
}class ReverseStrategy implements TransformStrategy {@Overridepublic String transform(String input) {return new StringBuilder(input).reverse().toString();}
}

结合两种方法

class StrategyProcessor extends DataProcessor {private TransformStrategy strategy;// 可以在运行时改变策略public void setStrategy(TransformStrategy strategy) {this.strategy = strategy;}@Overrideprotected String transformData(String input) {return strategy.transform(input);}
}public class Main {public static void main(String[] args) {StrategyProcessor strategyProcessor = new StrategyProcessor();String input = "hello world";// 策略1strategyProcessor.setStrategy(new UppercaseStrategy());strategyProcessor.process(input); // 输出:HELLO WORLD// 策略2strategyProcessor.setStrategy(new ReverseStrategy());strategyProcessor.process(input); // 输出:dlrow olleh}}

五、总结对比表

维度 模板方法模式 策略模式
核心思想 固定流程,可变步骤 算法互换,独立封装
关系类型 继承关系 组合关系
控制方向 父类控制子类 客户端控制算法
代码复用 通过继承复用模板代码 通过组合复用策略
灵活性 编译时确定算法结构 运行时切换算法
适用场景 算法骨架固定,步骤可变 多种算法需要动态选择
典型应用 框架、工作流、测试生命周期 支付方式、排序算法、压缩算法

选择指南:

  • 用模板方法当:你有固定的工作流程,但某些步骤需要定制化
  • 用策略模式当:你有多种算法,需要在运行时灵活切换
  • 结合使用当:既有固定流程,又需要在某些步骤使用不同策略
http://www.jsqmd.com/news/52159/

相关文章:

  • 节奏
  • mysql常用到的面试问题
  • 充电模块厂家哪家好,2025充电模块厂家权威榜单
  • 电源模块厂家哪家好,2025电源模块厂家公司盘点
  • 2025杭州办公室保洁哪家好?权威排行
  • 杭州公司日常保洁哪家好?2025杭州保洁公司精选榜单
  • 2025杭州商务楼保洁公司推荐综合实力榜单
  • 2025杭州保安公司综合实力榜单
  • 杭州保洁外包服务哪家好?2025精选杭州园区保洁公司榜单
  • 2025杭州专业物业管理公司权威排行
  • [zsh 专属配置 PS1 | 不依靠 oh my zsh]
  • 百航鹿大联训 roarctf_2019_easyheap
  • 图片云存储-七牛云
  • 彻底搞懂 Raft 算法:为“被理解”而生的分布式共识
  • 龙哥量化:初版简单的通达信公式回测案例_macd趋势策略收益曲线,展示在通达信的主副图(展示部分代码)
  • 代码随想录算法训练营第三章 哈希表part02
  • AI:情绪冲动和阴性症状有什么关系
  • 龙哥量化:简单的通达信公式回测案例_macd趋势策略收益曲线,展示在通达信的主副图(展示部分代码)
  • 光缆地图网站
  • AE表达式
  • 2025 Xhorse XDTPM1EN Universal Programmable TPMS Sensor: Supports 315/433MHz Key Tool Max Pro/MIDI
  • 2025年金蝶ERP服务商实施能力强、服务好——上海宝蝶深耕金蝶ERP管理系统、金蝶财务软件
  • 【论文阅读】DeltaLag: Learning Dynamic Lead-Lag Patterns in Financial Markets
  • Xhorse XDTPM1EN Universal Programmable TPMS Sensor 4pcs/lot – 315/433MHz for Key Tool Max Pro/MIDI
  • AI元人文:从价值对齐到价值共生的范式革命,及其在社会治理中的实践验证
  • 深入解剖 Redis 分布式锁:从 SETNX 到 Redlock 的演进之路
  • 闲话 25.11.26
  • oop-实验4 - fg
  • 揭开 Kafka 水位线的秘密:深度解析 LEO 与 HW 的同步机制
  • P1638 逛画展