优秀的编程知识分享平台

网站首页 > 技术文章 正文

模板方法模式 vs 回调Callback:谁才是高质量App

nanyue 2025-07-14 20:18:19 技术文章 1 ℃

模板方法模式 vs 回调Callback:谁才是高质量App的核心武器?


引言

在移动端开发中,我们每天都在用“模板方法”和“回调Callback”。你可能会问:“我的网络请求、页面生命周期、异步处理、事件响应,全都离不开回调。模板方法模式到底和Callback是什么关系?我应该用哪种方式来优化我的代码结构?”

本篇文章将用极其细致、工程化的方式,从原理到落地,结合Swift与Kotlin的案例,彻底讲清楚模板方法模式Callback回调函数的本质区别、联系与实战用法,帮你写出更高质量、更易维护的App业务代码。


一、什么是模板方法模式?(回顾)

模板方法模式,是一种行为型设计模式,它在基类中定义了一个算法流程的“模板骨架”,将一些步骤延迟到子类实现。这样可以保证整体流程不变,而每个子类可以只定制关键细节。

  • o 适合场景:业务流程一致,但细节实现有差异的场合。比如表单校验、页面生命周期、通用请求流程、自定义控件渲染等。
  • o 实现方式:父类(抽象基类)用final/abstract限制流程,关键步骤暴露为abstract或可重写方法。

二、什么是Callback回调函数?

Callback是一种编程技巧,指的是把一段函数/闭包作为参数传递,在特定事件/流程节点上被调用。它本质上是一种“反向调用”,即“流程控制权”暂时交给了调用者。

  • o 适合场景:异步任务(网络请求、动画、定时器)、事件监听(按钮点击、手势)、插件机制(自定义数据处理)等。
  • o 实现方式:闭包(Swift/Kotlin Lambda)或接口/协议。

三、核心区别与联系(原理对比)

模板方法模式Callback 回调函数 核心思想父类定流程,子类定细节外部传递函数/对象定细节流程控制权在类体系内部流程控制权交给外部(反转)关注点结构化、流程标准化、复用灵活性、扩展性、响应外部事件扩展方式继承/多态传递函数/实现接口典型场景生命周期、业务骨架、模板流程异步结果、事件监听、插件扩展

一句话总结:

  • o 模板方法适合“套路型”的流程复用,强调结构化和约束。
  • o Callback更灵活,强调事件响应和行为扩展,尤其适合异步/插件。

四、工程师日常高频实战场景对比

1. 页面/控件生命周期:模板方法模式

在页面或自定义控件的开发中,常常希望统一控制流程,但把关键点留给子类。

Swift 示例


    
    
    
  class BaseViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        setupViews()
        bindViewModel()
    }
    func setupViews() { fatalError("必须子类实现") }
    func bindViewModel() { }
}

class HomeViewController: BaseViewController {
    override func setupViews() {
        // 实现首页视图布局
    }
}

Kotlin 示例


    
    
    
  abstract class BaseActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setupViews()
        bindViewModel()
    }
    abstract fun setupViews()
    open fun bindViewModel() {}
}

class HomeActivity : BaseActivity() {
    override fun setupViews() {
        // 首页布局
    }
}

说明: 这里所有页面都“必须”实现setupViews(),流程不可变。适合统一生命周期、通用业务骨架的场景。


2. 网络请求/异步任务:Callback回调

网络请求、动画、定时器等大量异步操作,流程本身不可控,但我们需要在任务结束后做点事情。

Swift 示例


    
    
    
  func fetchUserData(completion: @escaping (Result<User, Error>) -> Void) {
    // 网络请求逻辑
    // ...
    completion(.success(user))
}
fetchUserData { result in
    switch result {
    case .success(let user):
        print("拿到用户数据:\(user)")
    case .failure(let error):
        print("请求失败:\(error)")
    }
}

Kotlin 示例


    
    
    
  fun fetchUserData(callback: (Result<User>) -> Unit) {
    // 网络请求
    callback(Result.success(User("Tom")))
}

fetchUserData { result ->
    result.onSuccess { user -> println("拿到用户数据:$user") }
    result.onFailure { error -> println("请求失败:$error") }
}

说明: 回调让你灵活指定异步后的行为,适合不可控/事件驱动/插件化的场景。


3. 结合使用:模板方法 + Callback

很多时候,两者并不是对立,而是组合使用,如“流程骨架+钩子回调”模式:

Swift 示例


    
    
    
  class DataUploader {
    final func upload(completion: @escaping (Bool) -> Void) {
        prepareUpload()
        performUpload { success in
            completion(success)
        }
        finishUpload()
    }
    func prepareUpload() { print("准备上传") }
    func performUpload(completion: @escaping (Bool) -> Void) {
        // 子类实现上传逻辑
        completion(true)
    }
    func finishUpload() { print("上传结束") }
}

Kotlin 示例


    
    
    
  abstract class DataUploader {
    fun upload(callback: (Boolean) -> Unit) {
        prepareUpload()
        performUpload { success ->
            callback(success)
        }
        finishUpload()
    }
    open fun prepareUpload() { println("准备上传") }
    open fun finishUpload() { println("上传结束") }
    abstract fun performUpload(callback: (Boolean) -> Unit)
}

五、为什么不能用Callback取代模板方法?(工程深度解析)

  1. 1. 结构 vs 灵活 o 模板方法强调结构化复用,适合统一标准、流程不可变的场景。o Callback强调行为灵活扩展,适合高度定制、流程不可控的异步/事件型业务。
  2. 2. 可维护性与可控性 o 模板方法模式让所有流程一目了然,可追踪、易维护。o Callback虽然灵活,但容易让流程分散、耦合增加,极端情况下出现“Callback Hell”。
  3. 3. 可读性与团队协作 o 统一流程减少歧义,便于多人协作和代码审查。o Callback若滥用,会导致代码分布零散,难以跟踪主流程。

六、典型移动端业务案例分析

  • o 页面/控件/生命周期:强烈建议用模板方法(统一流程,便于后续维护和扩展)。
  • o 异步数据请求/动画/事件驱动:Callback最佳选择(响应灵活)。
  • o 复杂业务建议组合使用:如网络请求带进度回调、上传/下载过程控制等。

七、最佳实践建议

  1. 1. 明确需求:流程是否可复用、标准化?选模板方法。高度定制、异步?选Callback。
  2. 2. 组合用法:需要流程+回调灵活处理时,两者结合,写出高质量代码。
  3. 3. 防止Callback Hell:多用async/await、Promise、协程等新式异步方案优化代码结构。

八、总结

  • o 模板方法和Callback是工程师的两大利器,分别适合不同场景。
  • o 不要用Callback滥刷一切流程,也不要用模板方法生搬硬套每一个细节。
  • o 合理搭配,工程质量和效率都能大幅提升!

Tags:

最近发表
标签列表