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

模板方法模式:优雅地封装算法骨架

在软件设计中,我们经常遇到这样的场景:多个类有相同的算法流程,但某些步骤的具体实现各不相同。模板方法模式通过定义算法骨架、延迟具体实现,完美解决了代码重复和流程控制问题。

一、真实案例:支付流程的烦恼

想象一下,你正在开发一个电商应用,需要接入多种支付方式:

// ❌ 重复的支付流程代码
class AlipayProcessor {fun processPayment(order: Order): PaymentResult {// 验证订单if (order.amount <= 0) throw IllegalArgumentException("金额无效")if (order.currency.isBlank()) throw IllegalArgumentException("货币无效")// 执行支付val transaction = alipayClient.pay(order.amount, order.currency)// 处理结果if (transaction.success) {order.status = OrderStatus.PAIDdatabase.updateOrder(order)notifyUser(order.userId, "支付成功")return PaymentResult.Success(transaction.id)} else {notifyUser(order.userId, "支付失败: ${transaction.error}")return PaymentResult.Failure(transaction.error)}}
}class WechatPayProcessor {fun processPayment(order: Order): PaymentResult {// 同样的验证逻辑,重复编写!if (order.amount <= 0) throw IllegalArgumentException("金额无效")if (order.currency.isBlank()) throw IllegalArgumentException("货币无效")// 不同的支付实现val transaction = wechatPayClient.createPayment(order)// 同样的结果处理逻辑,重复编写!if (transaction.isSuccess) {order.status = OrderStatus.PAIDdatabase.updateOrder(order)notifyUser(order.userId, "支付成功")return PaymentResult.Success(transaction.transactionId)} else {notifyUser(order.userId, "支付失败: ${transaction.errMsg}")return PaymentResult.Failure(transaction.errMsg)}}
}

问题很明显:​

  • ✅ 支付流程相同(验证→执行→更新订单→通知用户)

  • ❌ 相同逻辑被重复实现

  • ❌ 添加新支付方式需要重写所有逻辑

  • ❌ 修改流程需要修改所有处理器

二、模板方法模式登场

2.1 模式结构

模板方法模式包含两个核心部分:

  1. 抽象模板类​:定义算法骨架

  2. 具体实现类​:实现特定步骤

classDiagramclass PaymentProcessor {<<abstract>>+processPayment() PaymentResult#validateOrder() void#updateOrderStatus() void#notifyUser() void+executePayment()* PaymentTransaction+handleResult()* PaymentResult}class AlipayProcessor {+executePayment() PaymentTransaction+handleResult() PaymentResult}class WechatPayProcessor {+executePayment() PaymentTransaction+handleResult() PaymentResult}PaymentProcessor <|-- AlipayProcessorPaymentProcessor <|-- WechatPayProcessor

2.2 重构支付系统

// ✅ 使用模板方法模式重构
abstract class PaymentProcessor {// 模板方法 - 定义支付流程骨架fun processPayment(order: Order): PaymentResult {return try {validateOrder(order)           // 步骤1:验证订单val transaction = executePayment(order) // 步骤2:执行支付(抽象)updateOrderStatus(order, transaction) // 步骤3:更新订单notifyUser(order, transaction) // 步骤4:通知用户handleResult(transaction)     // 步骤5:处理结果(抽象)} catch (e: Exception) {handleError(order, e)         // 错误处理}}// 具体方法 - 通用实现private fun validateOrder(order: Order) {require(order.amount > 0) { "支付金额必须大于0" }require(order.currency.isNotBlank()) { "货币类型不能为空" }require(order.userId.isNotBlank()) { "用户ID不能为空" }println("✅ 订单验证通过")}private fun updateOrderStatus(order: Order, transaction: PaymentTransaction) {order.status = OrderStatus.PAIDorder.transactionId = transaction.idorder.updatedAt = System.currentTimeMillis()database.updateOrder(order)println("✅ 订单状态已更新")}private fun notifyUser(order: Order, transaction: PaymentTransaction) {val message = if (transaction.isSuccess) {"支付成功,订单号: ${order.id}"} else {"支付失败: ${transaction.errorMessage}"}notificationService.send(order.userId, message)println("✅ 用户已通知")}// 钩子方法 - 可选重写protected open fun handleError(order: Order, error: Exception): PaymentResult {println("❌ 支付处理失败: ${error.message}")notificationService.send(order.userId, "支付处理失败: ${error.message}")return PaymentResult.Failure(error.message ?: "未知错误")}// 抽象方法 - 子类必须实现protected abstract fun executePayment(order: Order): PaymentTransactionprotected abstract fun handleResult(transaction: PaymentTransaction): PaymentResult
}// 具体支付实现变得非常简单
class AlipayProcessor : PaymentProcessor() {override fun executePayment(order: Order): PaymentTransaction {println("🔵 支付宝支付执行中...")// 支付宝特定的支付逻辑return alipayClient.pay(order.amount, order.currency)}override fun handleResult(transaction: PaymentTransaction): PaymentResult {// 支付宝特定的结果处理return if (transaction.success) {PaymentResult.Success(transaction.id, "支付宝支付成功")} else {PaymentResult.Failure(transaction.error ?: "支付宝支付失败")}}
}class WechatPayProcessor : PaymentProcessor() {override fun executePayment(order: Order): PaymentTransaction {println("🟢 微信支付执行中...")// 微信支付特定的逻辑return wechatPayClient.createPayment(order)}override fun handleResult(transaction: PaymentTransaction): PaymentResult {// 微信支付特定的结果处理return if (transaction.isSuccess) {PaymentResult.Success(transaction.transactionId, "微信支付成功")} else {PaymentResult.Failure(transaction.errMsg ?: "微信支付失败")}}// 重写错误处理钩子override fun handleError(order: Order, error: Exception): PaymentResult {println("❌ 微信支付处理失败,进行特殊处理")// 微信支付特定的错误处理逻辑wechatPayClient.rollback(order.id)return super.handleError(order, error)}
}

三、Android 中的真实应用

3.1 Activity 生命周期模板

Android 框架本身就是模板方法模式的典范:

// Android Framework 中的模板方法
abstract class Activity {// 模板方法 - 控制Activity创建流程fun onCreate(savedInstanceState: Bundle?) {initializeWindow()      // 步骤1:窗口初始化(框架控制)setContentView()        // 步骤2:设置布局(框架控制)  onInitView()           // 步骤3:视图初始化(子类实现)onBindData()           // 步骤4:数据绑定(子类实现)onReady()              // 步骤5:准备完成(钩子方法)}private fun initializeWindow() {// Android框架控制的窗口初始化window.setBackgroundDrawableResource(android.R.color.background_light)}private fun setContentView() {// 调用抽象方法获取布局setContentView(getLayoutId())}// 抽象方法 - 子类必须实现protected abstract fun getLayoutId(): Intprotected abstract fun onInitView()protected abstract fun onBindData()// 钩子方法 - 子类可选择实现protected open fun onReady() {// 默认空实现}
}// 具体Activity实现
class MainActivity : Activity() {private lateinit var viewModel: MainViewModelprivate lateinit var recyclerView: RecyclerViewoverride fun getLayoutId(): Int = R.layout.activity_mainoverride fun onInitView() {// 只需关注视图初始化recyclerView = findViewById(R.id.recyclerView)recyclerView.layoutManager = LinearLayoutManager(this)findViewById<Button>(R.id.btnSubmit).setOnClickListener {onSubmit()}}override fun onBindData() {// 只需关注数据绑定viewModel = ViewModelProvider(this).get(MainViewModel::class.java)viewModel.items.observe(this) { items ->recyclerView.adapter = ItemAdapter(items)}}// 重写钩子方法添加额外逻辑override fun onReady() {super.onReady()// 添加额外的初始化逻辑setupAnalytics()checkNotifications()}private fun setupAnalytics() {// 分析工具初始化}private fun checkNotifications() {// 通知检查逻辑}
}

3.2 网络请求模板

// 网络请求模板
abstract class NetworkRequestTemplate<T> {// 模板方法suspend fun execute(): Result<T> {showLoading()                    // 步骤1:显示加载validateRequest()               // 步骤2:验证请求val response = performRequest() // 步骤3:执行请求(抽象)val result = handleResponse(response) // 步骤4:处理响应(抽象)hideLoading()                   // 步骤5:隐藏加载return result}// 具体方法private fun showLoading() {// 通用加载显示逻辑loadingState.value = true}private fun hideLoading() {// 通用加载隐藏逻辑loadingState.value = false}private fun validateRequest() {// 通用验证逻辑require(getUrl().isNotBlank()) { "请求URL不能为空" }}// 抽象方法protected abstract fun getUrl(): Stringprotected abstract suspend fun performRequest(): Responseprotected abstract fun handleResponse(response: Response): Result<T>// 钩子方法protected open fun onError(error: Exception): Result<T> {// 默认错误处理return Result.failure(error)}
}// 具体请求实现
class LoginRequest(private val username: String,private val password: String
) : NetworkRequestTemplate<User>() {override fun getUrl(): String = "${BASE_URL}/api/login"override suspend fun performRequest(): Response {return httpClient.post(getUrl()) {body = json {"username" to username"password" to password}}}override fun handleResponse(response: Response): Result<User> {return if (response.status.isSuccess()) {val user = parseUser(response.body)Result.success(user)} else {Result.failure(Exception("登录失败: ${response.status}"))}}// 重写错误处理override fun onError(error: Exception): Result<User> {// 登录特定的错误处理analytics.trackLoginError(error)return super.onError(error)}
}

四、模板方法模式的最佳实践

4.1 何时使用模板方法模式?

✅ 适合场景:​

  • 多个类有相同算法骨架,但某些步骤实现不同

  • 需要控制子类扩展,防止算法结构被破坏

  • 重要算法需要统一的执行顺序

  • 框架设计,希望用户遵循特定流程

❌ 不适合场景:​

  • 算法步骤经常变化(考虑策略模式)

  • 只有少数步骤不同(考虑函数参数化)

  • 类层次结构过于复杂

4.2 设计原则

// ✅ 好的模板方法设计
abstract class WellDesignedTemplate {// 模板方法应该是 final 的fun execute(): Result {step1()           // 固定步骤step2()           // 固定步骤  val data = step3() // 可变步骤(抽象)return step4(data) // 可变步骤(抽象)}// 具体方法 - 提供默认实现private fun step1() { /* 通用逻辑 */ }private fun step2() { /* 通用逻辑 */ }// 抽象方法 - 数量适中(2-5个)protected abstract fun step3(): Dataprotected abstract fun step4(data: Data): Result// 钩子方法 - 提供扩展点protected open fun onComplete(result: Result) {// 默认空实现}
}// ❌ 不好的设计
abstract class PoorlyDesignedTemplate {// 模板方法不是 final,容易被误改open fun execute() { /* ... */ }// 抽象方法过多,子类负担重abstract fun step1(): Dataabstract fun step2(): Dataabstract fun step3(): Dataabstract fun step4(): Dataabstract fun step5(): Data
}

4.3 与策略模式的区别

很多人容易混淆模板方法模式和策略模式,它们的区别在于:

方面

模板方法模式

策略模式

重点

算法骨架和流程控制

算法实现的互换

继承关系

使用类继承

使用对象组合

运行时

编译时确定结构

运行时切换算法

代码复用

通过继承复用代码

通过组合复用算法

// 模板方法模式 - 控制流程
abstract class ReportGenerator {// 固定生成流程fun generateReport(): Report {val data = fetchData()      // 抽象方法val processed = process(data) // 抽象方法return format(processed)    // 具体方法}abstract fun fetchData(): Dataabstract fun process(data: Data): ProcessedDataprivate fun format(data: ProcessedData): Report = TODO()
}// 策略模式 - 互换算法
class DataProcessor(private val strategy: ProcessingStrategy) {// 可互换的处理算法fun process(data: Data): Result {return strategy.execute(data) // 委托给策略对象}
}
interface ProcessingStrategy {fun execute(data: Data): Result
}

五、实际项目中的收益

在我们重构支付系统后,获得了显著收益:

5.1 代码质量提升

重构前:​

  • 每个支付处理器 50+ 行代码

  • 重复代码率 60%+

  • 添加新支付方式需要 1-2 天

重构后:​

  • 父类 40 行通用逻辑

  • 每个子类 10-15 行特定逻辑

  • 添加新支付方式只需 1-2 小时

5.2 维护性提升

// 添加新支付方式变得非常简单
class PayPalProcessor : PaymentProcessor() {override fun executePayment(order: Order): PaymentTransaction {println("🔵 PayPal支付执行中...")return payPalClient.createPayment(order)}override fun handleResult(transaction: PaymentTransaction): PaymentResult {return if (transaction.status == "COMPLETED") {PaymentResult.Success(transaction.id, "PayPal支付成功")} else {PaymentResult.Failure(transaction.error ?: "PayPal支付失败")}}
}// 业务流程修改只需改一处
abstract class PaymentProcessor {fun processPayment(order: Order): PaymentResult {validateOrder(order)logPaymentStart(order) // ✅ 新增步骤:只需在父类添加val transaction = executePayment(order)updateOrderStatus(order, transaction)notifyUser(order, transaction)logPaymentEnd(transaction) // ✅ 新增步骤:只需在父类添加return handleResult(transaction)}private fun logPaymentStart(order: Order) {analytics.track("payment_started", order.id)}private fun logPaymentEnd(transaction: PaymentTransaction) {analytics.track("payment_completed", transaction.id)}
}

六、总结

模板方法模式通过"好莱坞原则"(不要调用我们,我们会调用你)实现了:

  1. 代码复用​ - 将通用算法逻辑提升到父类

  2. 流程控制​ - 确保算法执行顺序一致性

  3. 扩展灵活​ - 通过钩子方法支持未来扩展

  4. 维护简单​ - 修改算法只需修改父类

适用场景:​

  • Android Activity/Fragment 基类设计

  • 业务流程处理器(支付、订单、审批等)

  • 框架和库的设计

  • 任何有固定流程但不同实现的场景

模板方法模式是构建可维护、可扩展系统的利器。下次当你发现多个类有相似流程时,考虑使用模板方法模式来消除重复,让代码更加优雅!

http://www.dtcms.com/a/549750.html

相关文章:

  • 有哪些做ppt用图片的网站有哪些免费咨询皮肤科医生在线
  • 理解 MySQL 架构:从连接到存储的全景视图
  • 电商网站 服务器易派客网站是谁做的
  • 大型语言模型(LLM)架构大比拼
  • 爱派(AiPy):一个让大语言模型直接操作Python完成任务
  • 【一加手机Bootloader解锁政策更新通知】
  • 什么是政企工作手机,有什么功能作用
  • 太原网站排名优化价格室内装修效果图网站有哪些
  • 深入探讨Python中三种核心数据结构:列表、字典和元组。
  • 建网站的几个公司通辽网站网站建设
  • 编辑 JAR 包内嵌套的 TXT 文件(Vim 操作)
  • 网站手机验证码如何做网站做链接代码
  • 无锡做网站6网站看不到预览图
  • Redis 限流最佳实践:令牌桶与滑动窗口全流程实现
  • *清理磁盘空间
  • 用什么软件做网站原型外贸退税流程及方法
  • 微软网站制作软件常见营销策略都有哪些
  • 全栈开源:一套源码快速构建电竞/体育直播平台(PC+H5+双端APP)
  • 淘宝网站维护用DW做的网站怎么弄成链接
  • 【C++】【常见面试题】最简版带大小和超时限制的LRU缓存实现
  • CSAPP实验2:Bomb
  • [人工智能-大模型-118]:模型层 - RNN状态记忆是如何实现的?是通过带权重的神经元,还是通过张量?
  • 手机做网站需要多少天国外代理ip地址和端口
  • Unity-WebGL开发——用IIS(Internet Information Services)部署webGL工程
  • 怎么仿制别人的网站一个网站的建设流程有哪些
  • 学生信息管理系统oracle
  • Angular【router路由】
  • 如何网站建设网页宣传片拍摄报价明细
  • 曲阜做网站智能建造概论
  • 嘉峪关网站seo英文商城网站