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

news/2025/11/27 4:31:51/文章来源:https://www.cnblogs.com/yaoee/p/19270712

一、模板方法模式 (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.mzph.cn/news/977814.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql常用到的面试问题

1. MySQL 数据库的主要备份方式有哪些?答案:主要备份方式包括全量备份(完整备份整个数据库)和增量备份(仅备份自上次备份以来发生变化的数据)。工具有 mysqldump、XtraBackup 和物理备份。 2. 如何确保 MySQL 数…

充电模块厂家哪家好,2025充电模块厂家权威榜单

随着新能源汽车的普及,充电模块作为充电桩的“心脏”,其性能直接决定了充电效率与安全。面对市场上众多的充电模块厂家,如何避开营销噱头,选择一家真正靠谱的合作伙伴成为许多企业与采购者的难题。本文将为您呈现一…

电源模块厂家哪家好,2025电源模块厂家公司盘点

电源模块作为电子设备的“心脏”,其性能与可靠性直接关系到整个系统的稳定运行。面对市场上众多的电源模块厂家,如何找到那些在特定领域深耕细作、技术过硬但可能并不广为人知的优质企业呢?本文将为您盘点8家在2025…

2025杭州办公室保洁哪家好?权威排行

2025杭州办公室保洁哪家好?权威排行。随着杭州民营经济的蓬勃发展和办公模式的不断升级,办公室保洁已从传统的“扫地擦桌”升级为影响办公效率、企业形象和员工健康的关键服务。如今,杭州办公室保洁市场需求持续增长…

杭州公司日常保洁哪家好?2025杭州保洁公司精选榜单

杭州公司日常保洁哪家好?2025杭州保洁公司精选榜单。随着杭州城市建设的加快和企业办公环境标准化要求的提高,保洁服务已经成为城市运转和企业运营中不可或缺的一环。目前杭州保洁行业呈现出多元化发展的态势,从最初…

2025杭州商务楼保洁公司推荐综合实力榜单

2025杭州商务楼保洁公司推荐综合实力榜单。在杭州城市更新与商务发展的双重推动下,开荒保洁和商务楼保洁成为两类需求旺盛的专业保洁服务。开荒保洁主要针对新建成的建筑,包括写字楼、住宅、厂房等,负责清除施工遗留…

2025杭州保安公司综合实力榜单

2025杭州保安公司综合实力榜单。作为城市安全保障体系的重要组成部分,保安服务已深度融入杭州的住宅小区、商业综合体、产业园区、企业单位等各类场景,核心职责涵盖门禁值守、巡逻防范、安全检查、应急处置等,直接关…

杭州保洁外包服务哪家好?2025精选杭州园区保洁公司榜单

杭州保洁外包服务哪家好?2025精选杭州园区保洁公司榜单。伴随杭州产业园区的密集布局和企业运营效率提升需求的增长,保洁外包服务和园区保洁服务已成为产业生态中不可或缺的组成部分。保洁外包服务指企业将内部保洁工…

2025杭州专业物业管理公司权威排行

2025杭州专业物业管理公司权威排行。随着杭州城市化进程加快和房地产市场的成熟,物业管理已成为保障居民生活、企业运营和城市治理的重要基础服务。物业管理服务涵盖小区住宅、商业综合体、产业园区等多个场景,核心内…

基于SSE技术加 deepseek 实现打字机回复效果

具体代码,已上传到厂库 git clone https://gitee.com/rush_peng/sse-deepseek-demo.gitSSE 技术 go 后端实现 package mainimport ("bufio""bytes""encoding/json""fmt"&quo…

[zsh 专属配置 PS1 | 不依靠 oh my zsh]

# -------------------------- Zsh 专属 PS1 配置(含空行+conda/venv/git) -------------------------- # 颜色定义(Zsh用%F{颜色},而非Bash的\033) COLOR_CONDA="%F{cyan}" # 青色(conda环境) CO…

百航鹿大联训 roarctf_2019_easyheap

我现在心如死灰,面如平湖,胸有惊雷。 这里面水太深,你把握不住。😅 checksec是NO PIE的。来看代码。同样改了改函数名。 __int64 __fastcall main(int a1, char **a2, char **a3) {int v3; // eaxint v4; // ebxi…

图片云存储-七牛云

图片云存储-七牛云一、介绍 在实际开发中,我们会有很多处理不同功能的服务器。例如:应用服务器:负责部署我们的应用数据库服务器:运行我们的数据库文件服务器:负责存储用户上传文件的服务器  分服务器处理的目的…

彻底搞懂 Raft 算法:为“被理解”而生的分布式共识

彻底搞懂 Raft 算法:为“被理解”而生的分布式共识彻底搞懂 Raft 算法:为“被理解”而生的分布式共识 在分布式系统的世界里,共识(Consensus)是一个核心难题:如何让一堆机器对某个值(比如数据记录)达成一致? …

龙哥量化:初版简单的通达信公式回测案例_macd趋势策略收益曲线,展示在通达信的主副图(展示部分代码)

3、函数buy,sell不能指定手数,只能在界面设置。 4、不识别第二个参数价格,所以, 你用上图中的10个价格之外的价格,在回测系统不起作用,比如实时突破压力线,代码中用压力线的价格成交,BUY(突破, 压力线),实际…

代码随想录算法训练营第三章 哈希表part02

代码随想录算法训练营第三章 哈希表part02第454题.四数相加II leetcode链接:https://leetcode.cn/problems/4sum-ii/description/ 题目描述:给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, …

AI:情绪冲动和阴性症状有什么关系

情感症状 和情绪冲动和阴性症状有什么关系 这个问题非常深刻,触及了精神病理学的核心。情感症状、情绪冲动与阴性症状的关系,与它们和阳性症状的关系完全不同,甚至可以说是相反的。 简单来说:阳性症状是正常功能的…

龙哥量化:简单的通达信公式回测案例_macd趋势策略收益曲线,展示在通达信的主副图(展示部分代码)

3、函数buy,sell不能指定手数,只能在界面设置。 4、不识别第二个参数价格,所以, 你用上图中的10个价格之外的价格,在回测系统不起作用,比如实时突破压力线,代码中用压力线的价格成交,BUY(突破, 压力线),实际…

光缆地图网站

光缆地图网站几个全球公认最权威、最好用的光缆地图网站,各有特色: 1. 行业标准级:TeleGeography Submarine Cable Map 这是全球电信行业最权威的数据来源,也是 UI 做得最好看的。网址:https://www.submarinecabl…

AE表达式

--本篇导航--如何使用表达式(打开删除,查看图形,错误)表达式的数组、赋值输入表达式、优先级一些常用的表达式(value,time,index,wiggle,random,loopOut,Math,if…else)表达式控制一些现成的表达式(可以…