引言:为什么要学习和使用设计模式?

  1. 代码质量提升: 可读性、可维护性、可扩展性。
  1. 团队协作: 提供通用语言,降低沟通成本。
  1. 架构基础: 是构建健壮、灵活应用架构的基石。
  1. 面试必备: 衡量开发设计能力和经验的重要指标。
  1. 解决特定问题: 为常见的软件设计问题提供经过验证的解决方案。

设计模式基础与原则

什么是设计模式?

  • 定义:在特定上下文中,针对常见问题的、可复用的解决方案。
  • 不是具体的代码,而是思想和模式
  • 分类:创建型、结构型、行为型 (GoF)。

面向对象设计原则 (SOLID)——设计模式的指导思想

  • S:单一职责原则 (Single Responsibility Principle - SRP)
    • eg: ViewModel 只负责UI状态和业务逻辑调用,Repository 只负责数据获取,Activity/Fragment 只负责UI展示和用户交互分发。
  • O:开闭原则 (Open/Closed Principle - OCP)
    • eg: 使用接口/抽象类定义扩展点(如 RecyclerView.Adapter 的不同 ViewHolder 类型),使用依赖注入方便替换实现。
  • L:里氏替换原则 (Liskov Substitution Principle - LSP)
    • eg: 确保自定义 View 或 Fragment 的子类可以无缝替换父类。
  • I:接口隔离原则 (Interface Segregation Principle - ISP)
    • eg: 定义功能明确的小接口,避免臃肿接口(如定义不同的点击监听接口)。
  • D:依赖倒置原则 (Dependency Inversion Principle - DIP)
    • eg: 依赖注入 (Hilt/Dagger, Koin) 的核心思想,高层模块不依赖低层模块的具体实现,都依赖抽象。ViewModel 依赖 Repository 接口而非具体实现。

创建型模式 (关注对象的创建)

单例模式 (Singleton Pattern)

  • 意图:保证一个类仅有一个实例,并提供一个全局访问点。
  • eg: 
    • object 关键字 (线程安全的懒加载单例)
    • Application Context 获取
    • 数据库实例 (RoomDatabase)
    • 网络请求客户端 (OkHttpClient, Retrofit)
    • 各种 Manager 类
💡
注意: 滥用单例可能导致耦合过高、测试困难。优先考虑依赖注入。

工厂方法模式 (Factory Method Pattern)

  • 意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类
  • eg: 
    • Fragment.newInstance(...) 静态工厂方法
    • ViewModelProvider.Factory 创建 ViewModel
    • Calendar.getInstance()

抽象工厂模式 (Abstract Factory Pattern)

  • 意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
  • eg: 不常用,但在需要支持多套UI主题或数据源切换的复杂场景中有用。

建造者模式 (Builder Pattern)

  • 意图:将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
  • eg: 
    • AlertDialog.Builder
    • NotificationCompat.Builder
    • Retrofit 构建 Retrofit 实例
    • Room 构建 RoomDatabase 实例
    • Kotlin DSL (如 Anko Layouts (已不推荐) 或 Compose UI 的构建方式)。Kotlin 的 apply 函数也常用于简化 Builder 风格的配置

原型模式 (Prototype Pattern)

  • 意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
  • eg: Kotlin 的 data class 提供的 copy() 方法天然支持原型模式的思想,用于创建状态副本(尤其在 MVI 架构中)。

结构型模式 (关注类与对象的组合)

适配器模式 (Adapter Pattern)

  • 意图:将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
  • eg:
    • RecyclerView.Adapter (连接数据与视图)
    • ArrayAdapter

装饰器模式 (Decorator Pattern)

  • 意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
  • eg: 
    • ContextWrapper (如 Activity, Application 都是 Context 的装饰)
    • BufferedReader 包装 Reader。在自定义 View 或 Drawable 时可能用到

代理模式 (Proxy Pattern)

  • 意图:为其他对象提供一种代理以控制对这个对象的访问。
  • eg: 
    • Retrofit 使用动态代理生成网络请求接口的实现
    • Room 可能使用代理进行懒加载
    • Android Framework 内部(如 Binder 机制)

外观模式 (Facade Pattern)

  • 意图:为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口使得这一子系统更加容易使用。
  • eg: Repository 模式通常扮演 Facade 角色,为 ViewModel 提供统一的数据访问接口,隐藏数据来源(网络、数据库、缓存)的复杂性。封装复杂的 SDK 或多个关联操作。

桥接模式 (Bridge Pattern)

  • 意图:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
  • eg: 不太直接常用,但思想体现在 UI 与逻辑分离、跨平台框架设计中。

组合模式 (Composite Pattern)

  • 意图:将对象组合成树形结构以表示“部分-整体”的层次结构。使得用户对单个对象和组合对象的使用具有一致性。
  • eg: View 和 ViewGroup 的关系就是典型的组合模式。ViewGroup 可以包含 View 或其他 ViewGroup。

享元模式 (Flyweight Pattern)

  • 意图:运用共享技术有效地支持大量细粒度的对象。
  • eg: RecyclerView 的 ViewHolder 复用机制体现了享元思想。绘图中共享画笔、颜色对象。

行为型模式 (关注对象间的交互与职责分配)

策略模式 (Strategy Pattern)

  • 意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
  • eg: 
    • 图片加载库 (Glide/Picasso) 的不同缓存策略
    • 不同的数据排序算法
    • 表单验证规则
    • 动画插值器 (Interpolator)

模板方法模式 (Template Method Pattern)

  • 意图:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
  • eg: 
    • Activity / Fragment 的生命周期回调方法 (onCreate, onViewCreated 等)
    • AsyncTask (已不推荐) 的 doInBackground, onPostExecute
    • 自定义 View 的 onMeasure, onDraw

观察者模式 (Observer Pattern)

  • 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
  • eg: 
    • LiveData
    • Kotlin StateFlow/SharedFlow
    • RxJava/RxKotlin
    • BroadcastReceiver
    • 各种 Listener (如 OnClickListener)

迭代器模式 (Iterator Pattern)

  • 意图:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
  • eg: 
    • Kotlin 集合框架 (List, Map, Set) 的 for 循环
    • Cursor 遍历数据库查询结果

责任链模式 (Chain of Responsibility Pattern)

  • 意图:为请求创建了一个接收者对象的链。这种模式让请求的发送者和接收者进行解耦。请求沿着链传递,直到有一个对象处理它为止。
  • eg: 
    • Android 事件分发机制 (Activity -> ViewGroup -> View 的 dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent
    • OkHttp 的 Interceptor 链

命令模式 (Command Pattern)

  • 意图:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
  • eg: 
    • 实现 Undo/Redo 功能
    • 将 UI 事件封装成命令传递给 ViewModel/Presenter

备忘录模式 (Memento Pattern)

  • 意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
  • eg: Activity/Fragment 的状态保存与恢复 (onSaveInstanceState, onRestoreInstanceState)

状态模式 (State Pattern)

  • 意图:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
  • eg: 
    • 管理复杂的 UI 状态(加载中、成功、失败、空数据)
    • 网络连接状态管理
    • 播放器状态(播放、暂停、停止)
💡
Kotlin 的 sealed class 非常适合用来实现状态模式。

访问者模式 (Visitor Pattern)

  • 意图:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
  • eg: 
    • ASM的classVisitor、methodVisitor
💡
在需要对复杂对象结构(如 AST 抽象语法树)进行多种不同操作时可能用到。

中介者模式 (Mediator Pattern)

  • 意图:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
  • eg: ViewModel 在 MVVM 中有时扮演中介者的角色,协调 UI (View) 和数据层 (Repository) 的交互。复杂的表单页面,各组件通过中介者协调状态。

解释器模式 (Interpreter Pattern)

  • 意图:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

总结与进阶

  1. 模式不是银弹: 理解每个模式的意图、适用场景、优缺点和潜在问题。
  1. 上下文是关键: 根据具体问题选择合适的模式,避免过度设计。
  1. 演进式设计: 从简单开始,根据需求变化逐步引入和重构模式。
  1. 实践出真知: 在实际项目中多应用、多思考、多总结。
  1. 阅读优秀源码: 学习 Android SDK、流行开源库 (OkHttp, Retrofit, Glide, Room, Hilt) 如何运用设计模式。
  1. 持续学习: 设计模式和架构思想在不断发展。
设计模式——创建型-工厂方法模式软件工程——常见软件需求风险和分析方法论
Loading...
Announcement
暂时没有公告!