在长期的项目迭代(从单体应用到组件化、模块化架构)中深刻体会到:设计原则是代码的“内功心法”,决定了代码的可维护性、可扩展性;设计模式则是“招式套路”,是原则落地的具体解决方案。脱离业务的设计是空中楼阁,而不懂原则与模式的开发,终将陷入“改一处崩一片”的技术债务。
本文将先深度拆解iOS开发核心设计原则,再按创建型、结构型、行为型三大类别,各精选5个高频设计模式,讲解其原理与iOS适配场景,全程不涉及代码,聚焦底层逻辑与实践取舍。
一、核心设计原则:iOS开发的“底层逻辑”
设计原则并非孤立存在,而是相互关联、相互约束的整体,其核心目标只有一个:降低系统耦合、提升代码复用,让系统在迭代中保持稳定且易于扩展。对于iOS开发而言,以下6个原则是重中之重,也是Apple官方API设计(如UIKit、Foundation)的核心遵循,更是后续设计模式落地的前提。
1. 单一职责原则(Single Responsibility Principle, SRP)
「原理拆解」:一个类/模块只负责一个核心职责,即“一个类只做一件事”。其本质是隔离关注点——每个职责对应一个变化维度,当需求变化时,只需要修改对应职责的类,避免牵一发而动全身,从根源上减少代码冲突与维护成本。
「iOS推荐场景」:
-
页面分层:ViewController只负责“页面展示与用户交互调度”,不处理网络请求、数据解析、业务逻辑(将这些职责拆分到NetworkManager、DataParser、ViewModel中),这也是iOS MVVM、VIPER架构的核心前提。
-
工具类设计:避免出现“万能工具类”(如CommonUtil),而是按功能拆分(如StringUtil、DateUtil、ImageUtil),每个工具类只处理一类相关操作,降低维护成本。
-
组件拆分:组件化开发中,每个组件只负责一个业务域(如支付组件、登录组件、商品组件),组件间通过接口通信,不跨域处理逻辑。
2. 开放-封闭原则(Open/Closed Principle, OCP)
「原理拆解」:软件实体(类、模块、接口)应当“对扩展开放,对修改关闭”。即通过扩展现有功能来应对需求变化,而非修改原有代码——这是避免引入新Bug、降低迭代风险的关键,也是组件化、模块化架构可扩展的核心保障。
「iOS推荐场景」:
-
需求迭代:如APP主题切换(浅色/深色/自定义主题),通过扩展Theme协议的实现类(LightTheme、DarkTheme),而非修改原有主题管理类的核心逻辑。
-
第三方SDK适配:如支付方式扩展(微信支付→新增支付宝支付),通过扩展Payment协议的实现类,原有支付调度逻辑无需修改,只需新增扩展类即可。
-
功能定制:如不同用户等级的权限展示,通过扩展Permission协议,针对普通用户、VIP用户实现不同的权限逻辑,不修改权限管理的核心流程。
3. 里氏替换原则(Liskov Substitution Principle, LSP)
「原理拆解」:子类必须能够替换其基类,且替换后不影响系统的正常运行。其本质是“子类继承基类的同时,不能破坏基类的行为契约”——子类可以扩展基类功能,但不能修改基类的核心逻辑,否则会导致系统逻辑混乱、难以调试。
「iOS推荐场景」:
-
基类与子类设计:如自定义UIView(BaseView),子类(CustomButtonView、CustomInputView)可以扩展点击事件、布局逻辑,但不能修改BaseView中已定义的生命周期(如layoutSubviews)、基础属性(如backgroundColor)的核心行为。
-
协议实现:如遵循UITableViewDataSource协议的类,无论如何实现协议方法,都必须保证返回的数据格式、数量符合协议约定,否则会导致UITableView渲染异常——这也是协议导向编程(POP)的核心遵循。
4. 依赖倒置原则(Dependency Inversion Principle, DIP)
「原理拆解」:高层模块不依赖低层模块,两者都依赖于抽象;抽象不依赖于具体实现,具体实现依赖于抽象。其核心是“面向抽象编程”,而非面向具体类编程,从而解除模块间的强耦合,让系统更具灵活性和可替换性。
「iOS推荐场景」:
-
组件化通信:高层业务组件(如订单组件)不依赖低层网络组件(如AFNetworking),而是依赖抽象的NetworkProtocol,网络组件的具体实现(AFNetworking、Alamofire)可以灵活替换,不影响业务逻辑。
-
ViewModel与Repository:ViewModel(高层)不依赖具体的网络请求类、本地存储类,而是依赖抽象的Repository协议,后续替换网络框架、存储方式(如Core Data→Realm)时,无需修改ViewModel。
-
依赖注入:如通过构造函数、属性注入的方式,将抽象依赖传递给高层模块,而非高层模块主动创建低层模块实例(如ViewModel初始化时注入Repository,而非在ViewModel内部创建Repository)。
5. 接口隔离原则(Interface Segregation Principle, ISP)
「原理拆解」:客户端不应该依赖它不需要的接口,即“拆分臃肿接口,建立专用接口”。避免出现“大而全”的接口,导致客户端被迫实现不需要的方法,增加耦合度,同时也能提升接口的可读性和可维护性。
「iOS推荐场景」:
-
协议设计:避免设计全能协议(如AllProtocol包含网络、存储、UI等所有方法),而是拆分为NetworkProtocol、StorageProtocol、UIProtocol,客户端根据需求只遵循对应的协议(如网络工具类只遵循NetworkProtocol)。
-
代理协议拆分:如自定义视图的代理协议,将“点击事件”“滑动事件”“数据回调事件”拆分为多个子协议(CustomViewTapDelegate、CustomViewScrollDelegate),避免代理类被迫实现不需要的代理方法。
6. 迪米特法则(Law of Demeter, LoD)
「原理拆解」:一个对象应该对其他对象尽可能少地了解,即“只与直接朋友通信,不与陌生人打交道”。其核心是降低对象间的耦合,减少不必要的依赖传递,让系统结构更清晰、更易于维护。
「iOS推荐场景」:
-
页面通信:ViewController之间不直接通信,而是通过中间件(如NotificationCenter、EventBus)、代理、Block传递消息,避免A页面直接调用B页面的方法,减少页面间的耦合。
-
多层级调用:避免出现“对象A→对象B→对象C→对象D”的链式调用,而是通过对象A直接调用对象D的抽象接口(或通过中间层转发),减少对象间的依赖链条。
-
工具类调用:业务类只调用工具类的公开接口,不关心工具类内部的实现细节(如调用ImageUtil压缩图片,无需关心压缩算法的具体逻辑)。
二、iOS高频设计模式:按类别深度解析
iOS开发中,按功能可将高频设计模式分为三大类:创建型(负责对象创建)、结构型(负责对象组合/结构优化)、行为型(负责对象交互/行为调度),每类精选5个最常用模式,聚焦原理与iOS实战场景,无需代码即可快速掌握核心用法。
(一)创建型设计模式:高效、规范创建对象
创建型模式的核心目标是“封装对象创建逻辑”,将对象创建与使用分离,避免重复创建、创建逻辑混乱等问题,同时贴合iOS特性,提升对象创建效率与可维护性。
1. 单例模式(Singleton)
「原理拆解」:保证一个类在整个应用生命周期中只有一个实例,并提供一个全局访问点。其核心是“唯一实例+全局访问”,本质是通过控制实例创建逻辑,避免重复创建对象造成的资源浪费,同时保证全局状态的统一性。
「核心目标」:共享资源、统一管理(如全局配置、网络请求、日志打印)。
「iOS推荐场景」:
-
全局配置类:如AppConfig(管理APP版本、接口地址、全局开关),整个应用只需要一个实例,保证配置的统一性。
-
网络管理类:如NetworkManager,统一处理网络请求、请求拦截、响应解析,避免多实例导致的请求冲突、配置混乱。
-
工具类:如LogUtil、ToastUtil,全局统一调用,无需重复创建实例,降低内存开销。
「注意」:避免滥用单例(如业务类、页面类不适合用单例),否则会导致内存泄漏、耦合度升高。
2. 工厂模式(Factory)
「原理拆解」:定义一个创建对象的接口,让子类决定实例化哪个类,本质是“封装对象创建逻辑”,将对象创建与使用分离,避免直接创建对象导致的耦合,同时统一对象创建规范。
「核心目标」:统一对象创建、降低耦合(如根据不同条件创建不同实例)。
「iOS推荐场景」:
-
视图创建:如根据不同类型创建不同的单元格(UITableViewCell),通过CellFactory根据cellType返回对应的cell实例,简化ViewController中的创建逻辑。
-
网络请求创建:如根据请求类型(GET/POST/PUT/DELETE),通过RequestFactory创建对应的请求实例,统一配置请求头、超时时间。
-
业务对象创建:如根据用户类型(普通用户/VIP用户),通过UserFactory创建对应的User实例,封装不同用户的初始化逻辑。
3. 原型模式(Prototype)
「原理拆解」:用一个已经创建的实例(原型)作为模板,通过复制(深拷贝/浅拷贝)的方式创建一个新的实例。其核心是“复制实例”,避免重复创建复杂对象,提升创建效率,同时保证新实例与原型的一致性。
「核心目标」:高效创建复杂对象、避免重复初始化。
「iOS推荐场景」:
-
复杂模型复制:如订单模型(OrderModel)包含多个子模型(商品、用户、地址),通过NSCopying协议实现深拷贝,快速创建一个与原模型一致的新模型,用于编辑、备份。
-
视图复制:如自定义视图(CustomView)包含复杂的子视图布局,通过复制原型视图,快速创建多个相同布局的视图(如列表中的重复单元格)。
-
配置复制:如全局配置模型(AppConfig),通过复制原型,创建不同场景下的配置实例(如测试环境、生产环境配置),避免重复初始化配置。
4. 抽象工厂模式(Abstract Factory)
「原理拆解」:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。其核心是“批量创建相关对象”,是工厂模式的延伸,适用于需要一组关联对象的场景,进一步降低耦合。
「核心目标」:批量创建关联对象、统一对象族的创建规范。
「iOS推荐场景」:
-
主题组件创建:如创建一套主题相关的组件(按钮、输入框、标题栏),通过ThemeAbstractFactory,根据主题类型(浅色/深色),批量创建对应主题的所有组件,保证主题统一性。
-
业务模块对象创建:如订单模块需要创建订单模型、订单详情模型、订单操作模型,通过OrderAbstractFactory,一次性创建该模块所需的所有关联对象,简化创建逻辑。
-
跨平台组件创建:如同时适配iOS和iPadOS的组件,通过DeviceAbstractFactory,根据设备类型,创建对应设备的组件(如iPad的分栏视图、iPhone的普通视图)。
5. 建造者模式(Builder)
「原理拆解」:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。其核心是“分步构建复杂对象”,将复杂对象的创建步骤拆分,灵活组合,避免创建逻辑臃肿。
「核心目标」:分步构建复杂对象、灵活配置对象属性。
「iOS推荐场景」:
-
复杂弹窗创建:如包含标题、内容、按钮、图标、输入框的自定义弹窗,通过Builder类,分步设置弹窗的各个属性(标题、内容、按钮数量),最终构建出所需弹窗,避免构造函数参数过多。
-
网络请求构建:如复杂的网络请求(包含请求头、请求参数、超时时间、缓存策略),通过RequestBuilder,分步配置请求的各个参数,灵活构建不同需求的网络请求。
-
模型构建:如包含多个可选属性的复杂模型(如用户资料模型),通过Builder类,分步设置模型的可选属性,无需创建多个构造函数,提升灵活性。
(二)结构型设计模式:优化对象组合,降低耦合
结构型模式的核心目标是“优化对象的组合方式”,通过合理的对象结构设计,降低模块间、对象间的耦合,提升代码的复用性和可扩展性,贴合iOS的UIKit架构设计思想。
1. 代理模式(Delegate)
「原理拆解」:定义两个对象之间的通信协议,让一个对象(代理方)替另一个对象(委托方)处理特定事件,本质是“解耦委托方与处理方”,将处理逻辑交给代理方,委托方只负责触发事件,不关心具体处理细节。
「核心目标」:解耦、事件分发(如UI交互事件、数据回调)。
「iOS推荐场景」:
-
UI组件交互:如UITableView的delegate(处理单元格点击、高度计算)、UIScrollView的delegate(处理滑动事件),这是UIKit中最核心的设计模式之一。
-
页面间通信:如子页面(Modal页面)通过代理将数据回调给父页面,避免子页面直接依赖父页面。
-
自定义组件:如自定义弹窗、自定义输入框,通过代理将用户操作(如确认、取消、输入完成)回调给使用方,组件本身不处理业务逻辑。
2. 装饰者模式(Decorator)
「原理拆解」:动态地给一个对象添加额外的职责,而不改变其原有的结构和功能。其核心是“组合优于继承”,通过包装对象的方式扩展功能,比继承更灵活,可实现多维度功能扩展。
「核心目标」:动态扩展功能、避免继承臃肿。
「iOS推荐场景」:
-
视图装饰:如给UIButton添加圆角、阴影、边框,通过Decorator类(如ButtonDecorator)动态添加这些属性,无需修改UIButton的子类。
-
网络请求装饰:如给请求添加签名、加密、日志打印功能,通过RequestDecorator包装原始请求,扩展请求能力,且不影响原始请求逻辑。
-
数据处理装饰:如对接口返回的数据进行过滤、转换、缓存,通过DataDecorator动态添加处理逻辑,可灵活组合多个装饰器(如先过滤再缓存)。
3. 适配器模式(Adapter)
「原理拆解」:将一个类的接口转换成客户端期望的另一个接口,使原本不兼容的类能够一起工作。其核心是“接口转换”,解决不同模块、不同SDK之间的接口不兼容问题,无需修改原有代码。
「核心目标」:兼容旧接口、整合第三方SDK。
「iOS推荐场景」:
-
第三方SDK适配:如项目中原本使用AFNetworking,后来替换为Alamofire,通过创建Adapter类(AlamofireAdapter),封装Alamofire的接口,使其与原有AFNetworking的接口一致,无需修改所有业务代码。
-
旧接口兼容:项目迭代中,旧接口被废弃,新接口与旧接口参数、返回格式不同,通过Adapter类将新接口转换为旧接口格式,保证旧业务代码正常运行。
-
跨平台适配:如Flutter与原生iOS通信,通过Adapter类转换Flutter的接口,使其适配iOS原生的调用方式。
4. 桥接模式(Bridge)
「原理拆解」:将抽象部分与它的实现部分分离,使它们都可以独立地变化。其核心是“分离抽象与实现”,避免抽象与实现绑定导致的扩展受限,提升系统的灵活性。
「核心目标」:分离抽象与实现、支持双向扩展。
「iOS推荐场景」:
-
视图与数据分离:如自定义图表视图(抽象部分),支持柱状图、折线图、饼图(实现部分),通过桥接模式,让图表视图与具体图表类型分离,可独立扩展图表类型或视图样式。
-
支付方式与支付逻辑分离:如支付抽象类(负责发起支付),具体支付方式(微信、支付宝、苹果内购)作为实现部分,通过桥接模式,可独立扩展支付方式或支付逻辑(如加密、签名)。
-
主题与组件分离:如主题抽象类(负责主题配置),具体组件(按钮、输入框)作为实现部分,通过桥接模式,可独立切换主题或扩展组件类型,无需修改主题逻辑。
5. 组合模式(Composite)
「原理拆解」:将对象组合成树形结构,以表示“部分-整体”的层次关系,使得用户对单个对象和组合对象的使用具有一致性。其核心是“统一单个对象与组合对象的调用方式”,简化层级结构的操作。
「核心目标」:统一层级对象调用、简化树形结构操作。
「iOS推荐场景」:
-
树形菜单创建:如APP的侧边栏菜单(包含一级菜单、二级菜单),通过组合模式,将单个菜单(叶子节点)和菜单组(组合节点)统一管理,统一处理菜单的点击、显示逻辑。
-
视图层级管理:如自定义容器视图(包含多个子视图,子视图又包含子视图),通过组合模式,统一管理所有子视图的布局、隐藏/显示、事件响应,无需分别操作每个子视图。
-
数据层级处理:如分类数据(一级分类包含多个二级分类,二级分类包含多个商品),通过组合模式,统一处理分类数据的加载、展示、筛选,简化层级数据的操作逻辑。
(三)行为型设计模式:规范对象交互,提升可维护性
行为型模式的核心目标是“规范对象之间的交互方式”,定义对象间的通信规则,解耦交互双方,提升代码的可维护性和可扩展性,适配iOS复杂的业务交互场景。
1. 观察者模式(Observer)
「原理拆解」:定义一种一对多的依赖关系,当一个对象(被观察者)的状态发生变化时,所有依赖它的对象(观察者)都会收到通知并自动更新。其核心是“发布-订阅”机制,解耦被观察者与观察者,支持事件广播。
「核心目标」:状态同步、事件广播(如全局状态变化、通知推送)。
「iOS推荐场景」:
-
全局状态同步:如用户登录状态变化,被观察者(UserManager)发送通知,观察者(首页、个人中心、购物车页面)收到通知后更新UI。
-
跨组件通信:组件化开发中,通过NotificationCenter(系统自带观察者实现)实现不同组件间的事件广播(如支付完成后,通知订单组件更新状态)。
-
数据变化监听:如Core Data数据更新、UserDefaults值变化,通过观察者模式触发UI刷新,无需主动轮询。
「注意」:避免过度使用NotificationCenter,否则会导致通知混乱、难以调试,优先使用代理、Block实现局部通信。
2. 策略模式(Strategy)
「原理拆解」:定义一系列算法,将每个算法封装起来,并使它们可以相互替换。其核心是“算法分离”,将算法的定义与使用分离,根据不同场景动态选择不同算法,避免多重if-else判断。
「核心目标」:算法灵活切换、避免多重if-else判断。
「iOS推荐场景」:
-
支付方式选择:如APP支持微信支付、支付宝支付、苹果内购,将每种支付方式封装为一个策略类(WeChatPayStrategy、AlipayStrategy),根据用户选择动态切换支付策略,无需修改支付调度逻辑。
-
数据排序:如列表数据支持按时间、按金额、按名称排序,将每种排序算法封装为策略类,根据用户选择动态切换排序策略。
-
缓存策略:如APP支持内存缓存、磁盘缓存、网络缓存,将每种缓存方式封装为策略类,根据数据类型(如图片、文本)动态选择缓存策略。
3. 命令模式(Command)
「原理拆解」:将一个请求封装成一个对象,从而使你可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。其核心是“请求封装”,解耦请求发起者与请求执行者。
「核心目标」:封装请求、支持请求排队与撤销。
「iOS推荐场景」:
-
操作记录与撤销:如文本编辑功能(输入、删除、替换),将每个操作封装为命令对象,记录操作日志,支持撤销、重做功能,无需耦合编辑逻辑与操作记录逻辑。
-
任务调度:如APP的后台任务(数据同步、日志上传、推送检测),将每个任务封装为命令对象,通过命令队列调度任务执行顺序,支持暂停、继续、取消任务。
-
按钮点击事件封装:如多个按钮对应不同的操作(保存、删除、提交),将每个按钮的操作封装为命令对象,统一管理按钮点击逻辑,提升可维护性。
4. 迭代器模式(Iterator)
「原理拆解」:提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。其核心是“统一遍历方式”,解耦聚合对象与遍历逻辑,支持多种遍历方式。
「核心目标」:统一遍历逻辑、隐藏聚合对象内部结构。
「iOS推荐场景」:
-
自定义集合遍历:如自定义数据集合(如分组列表数据),通过迭代器模式,定义统一的遍历接口,支持正序、倒序、过滤遍历,无需暴露集合内部的数据结构。
-
复杂数据遍历:如嵌套的树形数据(如分类数据),通过迭代器模式,封装遍历逻辑,支持深度优先、广度优先遍历,简化遍历代码。
-
跨集合遍历:如同时遍历数组、字典、Set中的数据,通过迭代器模式,定义统一的遍历接口,无需针对不同集合编写不同的遍历逻辑。
5. 备忘录模式(Memento)
「原理拆解」:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。其核心是“状态保存与恢复”,解耦对象状态与保存逻辑。
「核心目标」:保存对象状态、支持状态恢复。
「iOS推荐场景」:
-
页面状态保存:如表单编辑页面(用户输入的内容、选择的选项),通过备忘录模式,保存表单的当前状态,当页面退回到前台或重新进入时,恢复之前的编辑状态。
-
配置状态保存:如APP的设置页面(用户设置的主题、字体大小、通知开关),通过备忘录模式,保存配置状态,当APP重启后,恢复用户之前的设置。
-
编辑状态撤销:如图片编辑功能(裁剪、滤镜、旋转),通过备忘录模式,保存每次编辑后的状态,支持撤销操作,恢复到上一步编辑状态。
三、设计原则与模式的iOS实践心法
最后分享几点实践心得——设计原则与模式不是“教条”,而是“工具”,核心是“因地制宜”,而非“生搬硬套”,尤其在iOS开发中,需结合Apple官方API特性与业务场景灵活运用。
-
优先级:原则优先于模式。设计模式是原则的落地,若违背原则(如为了用单例而用单例),再好的模式也会导致代码臃肿、难以维护;所有模式的使用,都需围绕“降低耦合、提升复用”这一核心原则。
-
取舍:小项目无需过度设计。对于简单的工具类APP,无需引入复杂的模式(如抽象工厂、桥接模式),避免“过度设计”增加开发成本;对于中大型项目(如电商、社交APP),则需严格遵循原则,合理运用模式,为后续迭代铺路。
-
贴合iOS特性:充分利用Apple官方API的设计思想(如UIKit的代理、通知机制,Foundation的NSCopying协议),避免自己造轮子。例如,用NotificationCenter实现观察者模式,用NSCopying实现原型模式,无需重复实现底层逻辑。
-
长期视角:设计的核心是“可维护性”。短期内,不遵循原则、不用模式可能开发更快,但随着项目迭代(如人员变动、需求增加),技术债务会越来越重;长期来看,遵循原则、合理用模式,能大幅降低维护成本,提升开发效率。
总结
我们的目标不是“掌握所有模式”,而是理解每个原则、每个模式的核心逻辑,结合iOS业务场景(UI开发、组件化、性能优化)灵活运用——既不盲目追求“高大上”的模式,也不忽视基础原则的重要性。好的代码,是“可读、可维护、可扩展”的代码;而设计原则与模式,正是实现这一目标的核心工具。