<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>设计模式 on Last Stand</title><link>https://amatsuzero.github.io/LastStand/categories/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/</link><description>Recent content in 设计模式 on Last Stand</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sun, 21 Jun 2026 22:41:52 +0800</lastBuildDate><atom:link href="https://amatsuzero.github.io/LastStand/categories/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/index.xml" rel="self" type="application/rss+xml"/><item><title>代理模式</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/</guid><description>&lt;p&gt;在iOS开发中，&amp;ldquo;代理&amp;quot;这个词通常有两层含义：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;设计模式中的代理模式（Proxy Pattern）&lt;/strong&gt;：提供目标对象的替代品或占位符，控制对目标对象的访问&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;iOS中的代理模式（Delegate Pattern）&lt;/strong&gt;：一种基于协议的回调机制，用于对象间通信&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;虽然中文都叫&amp;quot;代理&amp;rdquo;，但它们是不同的设计模式，解决不同的问题。本文将两者都进行详细介绍。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一proxy-pattern代理模式"&gt;一、Proxy Pattern（代理模式）&lt;/h2&gt;
&lt;h3 id="定义"&gt;定义&lt;/h3&gt;
&lt;p&gt;代理模式（Proxy Pattern）是一种&lt;strong&gt;结构型设计模式&lt;/strong&gt;，它为其他对象提供一种代理以控制对这个对象的访问。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心思想&lt;/strong&gt;：代理对象作为真实对象的&amp;quot;替身&amp;quot;，客户端通过代理间接访问真实对象。代理可以在访问前后添加额外逻辑，而调用者对此毫不知情。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Client → Proxy → RealSubject
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↑
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 控制访问
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 添加功能
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 延迟创建
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;关键特征&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;代理对象与真实对象&lt;strong&gt;实现相同的接口&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;客户端&lt;strong&gt;不知道&lt;/strong&gt;自己使用的是代理还是真实对象&lt;/li&gt;
&lt;li&gt;代理对象&lt;strong&gt;持有&lt;/strong&gt;真实对象的引用（通常是强引用）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="模式结构"&gt;模式结构&lt;/h3&gt;
&lt;pre class="mermaid"&gt;classDiagram
class Subject {
&amp;lt;&amp;lt;interface&amp;gt;&amp;gt;
+request()
}
class RealSubject {
+request()
}
class Proxy {
-realSubject: RealSubject
+request()
}
class Client {
+useSubject()
}
Subject &lt;|.. RealSubject
Subject &lt;|.. Proxy
Proxy --&gt; RealSubject : delegates to
Client --&gt; Subject : uses
&lt;/pre&gt;
&lt;h3 id="proxy的类型"&gt;Proxy的类型&lt;/h3&gt;
&lt;h4 id="1-虚拟代理virtual-proxy"&gt;1. 虚拟代理（Virtual Proxy）&lt;/h4&gt;
&lt;p&gt;虚拟代理用于延迟创建开销大的对象，只有在真正需要时才创建：&lt;/p&gt;</description></item><item><title>单例模式</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h2 id="定义"&gt;定义&lt;/h2&gt;
&lt;p&gt;单例模式（Singleton Pattern）是一种创建型设计模式，它确保一个类只有一个实例，并提供一个全局访问点来获取该实例。&lt;/p&gt;
&lt;p&gt;单例模式的核心要点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;唯一性&lt;/strong&gt;：整个应用程序生命周期内只存在一个实例&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;全局访问&lt;/strong&gt;：提供一个全局访问点获取该实例&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;懒加载&lt;/strong&gt;：通常在第一次使用时才创建实例&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="为什么需要单例模式"&gt;为什么需要单例模式&lt;/h2&gt;
&lt;p&gt;单例模式要解决的核心问题是：&lt;strong&gt;确保某个类在整个应用中只有一个实例，并提供全局访问点&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题场景&lt;/strong&gt;：假设我们正在开发一个App，需要管理用户的登录状态和用户信息。&lt;/p&gt;
&lt;p&gt;如果不使用单例，可能会遇到这样的问题：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UserManager&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; currentUser: User?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; isLoggedIn: Bool = &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;login&lt;/span&gt;(user: User) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; currentUser = user
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; isLoggedIn = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 在登录页面&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; userManager1 = UserManager()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;userManager1.login(user: user)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 在个人中心页面&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; userManager2 = UserManager()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(userManager2.isLoggedIn) &lt;span style="color:#75715e"&gt;// false！因为是不同的实例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种方式有什么问题？&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;状态不一致&lt;/strong&gt;：不同地方创建的UserManager是不同的实例，它们的状态相互独立，导致登录状态无法共享&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;资源浪费&lt;/strong&gt;：如果UserManager管理的是数据库连接、网络会话等资源，创建多个实例会浪费系统资源&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据同步困难&lt;/strong&gt;：多个实例之间的数据需要手动同步，容易出错&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;单例模式的解决思路&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;单例模式确保整个应用只有一个UserManager实例，所有地方都访问同一个对象：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UserManager&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; shared = UserManager()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;() {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; currentUser: User?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; isLoggedIn: Bool = &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;login&lt;/span&gt;(user: User) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; currentUser = user
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; isLoggedIn = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 在登录页面&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;UserManager.shared.login(user: user)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 在个人中心页面&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(UserManager.shared.isLoggedIn) &lt;span style="color:#75715e"&gt;// true！同一个实例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;适合使用单例的场景&lt;/strong&gt;：&lt;/p&gt;</description></item><item><title>命令模式</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E5%91%BD%E4%BB%A4%E6%A8%A1%E5%BC%8F/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E5%91%BD%E4%BB%A4%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h2 id="定义"&gt;定义&lt;/h2&gt;
&lt;p&gt;命令模式（Command Pattern）是一种行为型设计模式，它将请求封装成对象，从而可以用不同的请求对客户进行参数化，对请求排队或记录请求日志，以及支持可撤销的操作。&lt;/p&gt;
&lt;p&gt;命令模式的核心思想是：将&amp;quot;请求&amp;quot;封装成一个对象，使得可以用不同的请求、队列或日志来参数化其他对象，同时支持可撤销操作。&lt;/p&gt;
&lt;h2 id="为什么需要命令模式"&gt;为什么需要命令模式&lt;/h2&gt;
&lt;p&gt;命令模式要解决的核心问题是：&lt;strong&gt;将请求（操作）封装成对象，使得可以对请求进行存储、传递、撤销等操作&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题场景&lt;/strong&gt;：假设我们正在开发一个文本编辑器，需要支持撤销/重做功能。&lt;/p&gt;
&lt;p&gt;最直接的方式可能是这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TextEditor&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; text: String = &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;insertText&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; newText: String, at position: Int) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; index = text.index(text.startIndex, offsetBy: position)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; text.insert(contentsOf: newText, at: index)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;deleteText&lt;/span&gt;(from start: Int, length: Int) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; startIndex = text.index(text.startIndex, offsetBy: start)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; endIndex = text.index(startIndex, offsetBy: length)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; text.removeSubrange(startIndex..&amp;lt;endIndex)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 用户操作&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; editor = TextEditor()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;editor.insertText(&lt;span style="color:#e6db74"&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;, at: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;editor.insertText(&lt;span style="color:#e6db74"&gt;&amp;#34; World&amp;#34;&lt;/span&gt;, at: &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;editor.deleteText(from: &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, length: &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 如何实现撤销？需要记住每次操作的类型、参数、以及如何逆向执行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 这变得非常复杂...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种方式有什么问题？&lt;/p&gt;</description></item><item><title>外观模式</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E5%A4%96%E8%A7%82%E6%A8%A1%E5%BC%8F/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E5%A4%96%E8%A7%82%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h2 id="定义"&gt;定义&lt;/h2&gt;
&lt;p&gt;外观模式（Facade Pattern）是一种结构型设计模式，它为子系统中的一组接口提供一个统一的高层接口。外观模式定义了一个高层接口，使得子系统更加容易使用。&lt;/p&gt;
&lt;p&gt;外观模式的核心思想是通过引入一个外观类，将复杂子系统的内部复杂性隐藏起来，只暴露一个简单的接口给客户端。&lt;/p&gt;
&lt;h2 id="为什么需要外观模式"&gt;为什么需要外观模式&lt;/h2&gt;
&lt;p&gt;外观模式要解决的核心问题是：&lt;strong&gt;简化复杂子系统的使用，为客户端提供一个更简单的接口&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题场景&lt;/strong&gt;：假设我们正在开发一个视频播放功能，需要处理音频、视频、字幕等多个子系统。&lt;/p&gt;
&lt;p&gt;直接使用各个子系统：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;VideoPlayerController&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;playVideo&lt;/span&gt;(url: URL) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 1. 初始化音频引擎&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; audioEngine = AudioEngine()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; audioEngine.configure(sampleRate: &lt;span style="color:#ae81ff"&gt;44100&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; audioEngine.setOutputDevice(.speaker)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 2. 初始化视频解码器&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; videoDecoder = VideoDecoder()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; videoDecoder.setCodec(.h264)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; videoDecoder.configureHardwareAcceleration(&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 3. 初始化渲染器&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; renderer = VideoRenderer()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; renderer.setResolution(&lt;span style="color:#ae81ff"&gt;1920&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1080&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; renderer.setFrameRate(&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 4. 加载字幕&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; subtitleLoader = SubtitleLoader()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; subtitles = subtitleLoader.load(from: url)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 5. 同步各个组件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; synchronizer = AVSynchronizer()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; synchronizer.link(audio: audioEngine, video: videoDecoder)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 6. 开始播放&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; data = loadVideoData(url)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; decodedVideo = videoDecoder.decode(data)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; renderer.render(decodedVideo)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; audioEngine.play()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 还要处理暂停、seek、音量调节...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种方式有什么问题？&lt;/p&gt;</description></item><item><title>工厂模式</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h2 id="定义"&gt;定义&lt;/h2&gt;
&lt;p&gt;工厂模式（Factory Pattern）是一种创建型设计模式，它提供了一种创建对象的方式，将对象的创建逻辑与使用逻辑分离。工厂模式有三种变体：简单工厂模式、工厂方法模式和抽象工厂模式。&lt;/p&gt;
&lt;h2 id="为什么需要工厂模式"&gt;为什么需要工厂模式&lt;/h2&gt;
&lt;p&gt;工厂模式要解决的核心问题是：&lt;strong&gt;将对象的创建过程与使用过程分离&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题场景&lt;/strong&gt;：假设我们正在开发一个网络层，需要创建URLSession对象。&lt;/p&gt;
&lt;p&gt;直接使用构造函数创建对象看起来很简单：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NetworkManager&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fetchData&lt;/span&gt;(from url: URL) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 直接创建URLSession&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; config = URLSessionConfiguration.&lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; config.timeoutIntervalForRequest = &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; config.httpAdditionalHeaders = [&lt;span style="color:#e6db74"&gt;&amp;#34;Authorization&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Bearer xxx&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; session = URLSession(configuration: config)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; session.dataTask(with: url) { data, response, error &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 处理响应...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }.resume()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种方式有什么问题？&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;创建逻辑与业务逻辑混在一起&lt;/strong&gt;：&lt;code&gt;fetchData&lt;/code&gt;方法既要负责创建session，又要负责发起请求，职责不单一&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;创建逻辑无法复用&lt;/strong&gt;：如果另一个方法也需要相同配置的session，只能复制这段创建代码&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;难以替换实现&lt;/strong&gt;：如果想在测试时使用Mock的session，或者在不同环境使用不同配置，需要修改业务代码&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;隐藏了依赖关系&lt;/strong&gt;：从方法签名看不出这个类依赖URLSession，依赖关系被隐藏在方法内部&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;工厂模式的解决思路&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;工厂模式的核心是：&lt;strong&gt;调用方不再自己new对象，而是向工厂&amp;quot;要&amp;quot;对象&lt;/strong&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 工厂负责创建&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;URLSessionFactory&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;createDefault&lt;/span&gt;() -&amp;gt; URLSession {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; config = URLSessionConfiguration.&lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; config.timeoutIntervalForRequest = &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; config.httpAdditionalHeaders = [&lt;span style="color:#e6db74"&gt;&amp;#34;Authorization&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Bearer xxx&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; URLSession(configuration: config)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;createBackground&lt;/span&gt;(identifier: String) -&amp;gt; URLSession {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; config = URLSessionConfiguration.background(withIdentifier: identifier)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; URLSession(configuration: config)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 业务代码只负责使用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NetworkManager&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; session: URLSession
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(session: URLSession = URLSessionFactory.createDefault()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.session = session
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fetchData&lt;/span&gt;(from url: URL) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; session.dataTask(with: url) { data, response, error &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 处理响应...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }.resume()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样做的好处：&lt;/p&gt;</description></item><item><title>建造者模式</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E5%BB%BA%E9%80%A0%E8%80%85%E6%A8%A1%E5%BC%8F/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E5%BB%BA%E9%80%A0%E8%80%85%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h2 id="定义"&gt;定义&lt;/h2&gt;
&lt;p&gt;建造者模式（Builder Pattern）是一种创建型设计模式，它将复杂对象的构建与表示分离，使得同样的构建过程可以创建不同的表示。建造者模式特别适用于创建包含多个可选参数的对象。&lt;/p&gt;
&lt;p&gt;建造者模式的核心思想是：将一个复杂对象的构建过程分解为多个简单的步骤，通过一步一步地构建，最终得到完整的对象。&lt;/p&gt;
&lt;h2 id="为什么需要建造者模式"&gt;为什么需要建造者模式&lt;/h2&gt;
&lt;p&gt;建造者模式要解决的核心问题是：&lt;strong&gt;简化复杂对象的创建过程，特别是当对象有很多可选参数时&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题场景&lt;/strong&gt;：假设我们需要创建一个网络请求配置对象，它有很多可选参数。&lt;/p&gt;
&lt;p&gt;使用构造函数的方式：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NetworkConfig&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; baseURL: URL
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; timeout: TimeInterval
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; retryCount: Int
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; cachePolicy: CachePolicy
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; headers: [String: String]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; enableLogging: Bool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; certificatePinning: Bool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 构造函数参数太多！&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(baseURL: URL,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; timeout: TimeInterval = &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; retryCount: Int = &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cachePolicy: CachePolicy = .&lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; headers: [String: String] = [:],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; enableLogging: Bool = &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; certificatePinning: Bool = &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 使用时 - 参数太多，难以阅读&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; config = NetworkConfig(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; baseURL: URL(string: &lt;span style="color:#e6db74"&gt;&amp;#34;https://api.example.com&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;!&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; timeout: &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; retryCount: &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cachePolicy: .reloadIgnoringCache,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; headers: [&lt;span style="color:#e6db74"&gt;&amp;#34;Authorization&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Bearer token&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; enableLogging: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; certificatePinning: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种方式有什么问题？&lt;/p&gt;</description></item><item><title>生产者消费者模式</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E7%94%9F%E4%BA%A7%E8%80%85%E6%B6%88%E8%B4%B9%E8%80%85%E6%A8%A1%E5%BC%8F/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E7%94%9F%E4%BA%A7%E8%80%85%E6%B6%88%E8%B4%B9%E8%80%85%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h2 id="定义"&gt;定义&lt;/h2&gt;
&lt;p&gt;生产者消费者模式（Producer-Consumer Pattern）是一种并发设计模式，它通过一个共享的缓冲区来解耦生产者和消费者，使得生产者和消费者可以以不同的速度工作，而不需要直接相互依赖。&lt;/p&gt;
&lt;p&gt;生产者负责产生数据并放入缓冲区，消费者从缓冲区中取出数据进行处理。这种模式是多线程编程中最经典的设计模式之一。&lt;/p&gt;
&lt;h2 id="为什么需要生产者消费者模式"&gt;为什么需要生产者消费者模式&lt;/h2&gt;
&lt;p&gt;生产者消费者模式要解决的核心问题是：&lt;strong&gt;如何在生产者和消费者处理速度不一致的情况下，实现高效、安全的数据传递&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题场景&lt;/strong&gt;：假设我们正在开发一个图片处理App，用户选择多张图片后需要进行滤镜处理。图片加载速度快，但滤镜处理速度慢。&lt;/p&gt;
&lt;p&gt;最直接的方式可能是这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ImageProcessor&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;processImages&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; urls: [URL]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; url &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; urls {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 加载图片（快）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; image = loadImage(from: url)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 应用滤镜（慢）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; filtered = applyFilter(to: image)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 保存结果&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; saveImage(filtered)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;loadImage&lt;/span&gt;(from url: URL) -&amp;gt; UIImage { &lt;span style="color:#75715e"&gt;/* ... */&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;applyFilter&lt;/span&gt;(to image: UIImage) -&amp;gt; UIImage { &lt;span style="color:#75715e"&gt;/* ... */&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;saveImage&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; image: UIImage) { &lt;span style="color:#75715e"&gt;/* ... */&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种方式有什么问题？&lt;/p&gt;</description></item><item><title>策略模式</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h2 id="定义"&gt;定义&lt;/h2&gt;
&lt;p&gt;策略模式（Strategy Pattern）是一种行为型设计模式，它定义了一系列算法，将每个算法封装起来，并使它们可以相互替换。策略模式让算法独立于使用它的调用者而变化。&lt;/p&gt;
&lt;p&gt;策略模式的核心思想是：将算法的定义与使用分离，通过组合而非继承来实现算法的切换。&lt;/p&gt;
&lt;h2 id="为什么需要策略模式"&gt;为什么需要策略模式&lt;/h2&gt;
&lt;p&gt;在实际开发中，我们经常会遇到这样的场景：同一个功能有多种实现方式，而且这些实现方式需要根据不同条件进行切换。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题场景&lt;/strong&gt;：假设我们正在开发一个电商App的支付功能，需要支持信用卡、Apple Pay、支付宝等多种支付方式。&lt;/p&gt;
&lt;p&gt;最直接的实现方式可能是这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;processPayment&lt;/span&gt;(type: String, amount: Double) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; type == &lt;span style="color:#e6db74"&gt;&amp;#34;creditCard&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 信用卡支付逻辑（可能有几十行代码）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;Processing credit card payment...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; type == &lt;span style="color:#e6db74"&gt;&amp;#34;applePay&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Apple Pay支付逻辑&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;Processing Apple Pay...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; type == &lt;span style="color:#e6db74"&gt;&amp;#34;alipay&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 支付宝支付逻辑&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;Processing Alipay...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 后续可能还要添加更多支付方式...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种实现方式存在几个明显的问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;违反开闭原则&lt;/strong&gt;：每次添加新的支付方式，都需要修改这个函数，增加新的分支&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;代码臃肿&lt;/strong&gt;：随着支付方式增多，函数会变得越来越长，难以维护&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;测试困难&lt;/strong&gt;：所有支付逻辑耦合在一起，难以单独测试某种支付方式&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;复用性差&lt;/strong&gt;：如果其他地方也需要使用某种支付逻辑，只能复制代码&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;策略模式的解决思路&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;策略模式将每种支付方式抽取为独立的类（策略），它们都实现相同的接口。调用方只需要持有策略接口的引用，不需要知道具体是哪种实现。&lt;/p&gt;
&lt;p&gt;这样做的好处是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;新增支付方式&lt;/strong&gt;：只需要新建一个策略类，无需修改现有代码&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;代码清晰&lt;/strong&gt;：每种支付逻辑独立封装，职责单一&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;易于测试&lt;/strong&gt;：可以对每种策略单独进行单元测试&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;运行时切换&lt;/strong&gt;：用户可以随时切换支付方式，系统只需要替换策略对象&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;简单来说，策略模式就是把「做什么」和「怎么做」分离开来——调用方只关心「做什么」，具体「怎么做」由不同的策略类来决定。&lt;/p&gt;
&lt;h2 id="模式结构"&gt;模式结构&lt;/h2&gt;
&lt;pre class="mermaid"&gt;classDiagram
class Context {
-strategy: Strategy
+setStrategy(strategy: Strategy)
+executeStrategy()
}
class Strategy {
&amp;lt;&amp;lt;interface&amp;gt;&amp;gt;
+execute()
}
class ConcreteStrategyA {
+execute()
}
class ConcreteStrategyB {
+execute()
}
class ConcreteStrategyC {
+execute()
}
Context o-- Strategy
Strategy &lt;|.. ConcreteStrategyA
Strategy &lt;|.. ConcreteStrategyB
Strategy &lt;|.. ConcreteStrategyC
&lt;/pre&gt;
&lt;h2 id="角色说明"&gt;角色说明&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Strategy（策略接口）&lt;/strong&gt;：定义所有支持的算法的公共接口&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ConcreteStrategy（具体策略）&lt;/strong&gt;：实现Strategy接口的具体算法&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context（上下文）&lt;/strong&gt;：持有Strategy的引用，负责调用策略方法&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ios中的实现"&gt;iOS中的实现&lt;/h2&gt;
&lt;h3 id="基础实现"&gt;基础实现&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 策略协议&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;protocol&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PaymentStrategy&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pay&lt;/span&gt;(amount: Double) -&amp;gt; Bool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; name: String { &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 具体策略 - 信用卡支付&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CreditCardPayment&lt;/span&gt;: PaymentStrategy {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; cardNumber: String
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; cvv: String
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; name: String { &lt;span style="color:#e6db74"&gt;&amp;#34;Credit Card&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(cardNumber: String, cvv: String) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.cardNumber = cardNumber
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.cvv = cvv
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pay&lt;/span&gt;(amount: Double) -&amp;gt; Bool {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;Paying &lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(&lt;/span&gt;amount&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt; using Credit Card ending with &lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(&lt;/span&gt;cardNumber.suffix&lt;span style="color:#e6db74"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&lt;span style="color:#e6db74"&gt;))&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 实际支付逻辑&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 具体策略 - Apple Pay&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ApplePayPayment&lt;/span&gt;: PaymentStrategy {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; name: String { &lt;span style="color:#e6db74"&gt;&amp;#34;Apple Pay&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pay&lt;/span&gt;(amount: Double) -&amp;gt; Bool {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;Paying &lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(&lt;/span&gt;amount&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt; using Apple Pay&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 调用Apple Pay SDK&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 上下文&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PaymentContext&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; strategy: PaymentStrategy
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(strategy: PaymentStrategy) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.strategy = strategy
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setStrategy&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; strategy: PaymentStrategy) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.strategy = strategy
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;checkout&lt;/span&gt;(amount: Double) -&amp;gt; Bool {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;Processing payment with &lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(&lt;/span&gt;strategy.name&lt;span style="color:#e6db74"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; strategy.pay(amount: amount)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 使用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; creditCard = CreditCardPayment(cardNumber: &lt;span style="color:#e6db74"&gt;&amp;#34;1234567890123456&amp;#34;&lt;/span&gt;, cvv: &lt;span style="color:#e6db74"&gt;&amp;#34;123&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; context = PaymentContext(strategy: creditCard)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;context.checkout(amount: &lt;span style="color:#ae81ff"&gt;99.99&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 切换支付方式&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; applePay = ApplePayPayment()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;context.setStrategy(applePay)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;context.checkout(amount: &lt;span style="color:#ae81ff"&gt;99.99&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="使用闭包简化策略"&gt;使用闭包简化策略&lt;/h3&gt;
&lt;p&gt;对于简单的策略，可以使用闭包代替完整的类：&lt;/p&gt;</description></item><item><title>装饰器模式</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E8%A3%85%E9%A5%B0%E5%99%A8%E6%A8%A1%E5%BC%8F/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E8%A3%85%E9%A5%B0%E5%99%A8%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h2 id="定义"&gt;定义&lt;/h2&gt;
&lt;p&gt;装饰器模式（Decorator Pattern）是一种结构型设计模式，它允许向现有对象动态添加新功能，同时又不改变其结构。装饰器通过创建一个包装对象来包裹真实对象，实现在不修改原有对象的基础上扩展功能。&lt;/p&gt;
&lt;p&gt;装饰器模式的核心思想是：使用组合而非继承来扩展对象的功能，遵循&amp;quot;对扩展开放，对修改关闭&amp;quot;的原则。&lt;/p&gt;
&lt;h2 id="为什么需要装饰器模式"&gt;为什么需要装饰器模式&lt;/h2&gt;
&lt;p&gt;装饰器模式要解决的核心问题是：&lt;strong&gt;在不修改原有对象的情况下，动态地给对象添加新功能&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id="问题场景"&gt;问题场景&lt;/h3&gt;
&lt;p&gt;假设我们正在开发一个UI组件库，需要为&lt;code&gt;UILabel&lt;/code&gt;添加各种视觉效果：圆角、阴影、边框、渐变背景等。而且这些效果需要能够&lt;strong&gt;自由组合&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id="方案一使用继承不推荐"&gt;方案一：使用继承（不推荐）&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 基础标签&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;BasicLabel&lt;/span&gt;: UILabel {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(text: String) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(frame: .zero)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.text = text
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 圆角标签&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RoundedLabel&lt;/span&gt;: BasicLabel {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(text: String) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(text: text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; layer.cornerRadius = &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; clipsToBounds = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 阴影标签&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ShadowLabel&lt;/span&gt;: BasicLabel {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(text: String) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(text: text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; layer.shadowColor = UIColor.black.cgColor
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; layer.shadowOffset = CGSize(width: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, height: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; layer.shadowOpacity = &lt;span style="color:#ae81ff"&gt;0.3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 边框标签&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;BorderLabel&lt;/span&gt;: BasicLabel {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(text: String) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(text: text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; layer.borderWidth = &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; layer.borderColor = UIColor.gray.cgColor
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 如果需要圆角+阴影呢？&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RoundedShadowLabel&lt;/span&gt;: BasicLabel {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(text: String) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(text: text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 重复圆角代码&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; layer.cornerRadius = &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; clipsToBounds = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 重复阴影代码&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; layer.shadowColor = UIColor.black.cgColor
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; layer.shadowOffset = CGSize(width: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, height: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; layer.shadowOpacity = &lt;span style="color:#ae81ff"&gt;0.3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 如果需要圆角+边框呢？&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RoundedBorderLabel&lt;/span&gt;: BasicLabel { &lt;span style="color:#75715e"&gt;/* 又要重复代码 */&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 如果需要阴影+边框呢？&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ShadowBorderLabel&lt;/span&gt;: BasicLabel { &lt;span style="color:#75715e"&gt;/* 继续重复代码 */&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 如果需要圆角+阴影+边框呢？&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RoundedShadowBorderLabel&lt;/span&gt;: BasicLabel { &lt;span style="color:#75715e"&gt;/* 所有代码都重复一遍 */&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;这种方式的问题&lt;/strong&gt;：&lt;/p&gt;</description></item><item><title>观察者模式</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h2 id="定义"&gt;定义&lt;/h2&gt;
&lt;p&gt;观察者模式（Observer Pattern）是一种行为型设计模式，它定义了对象之间的一对多依赖关系，当一个对象（主题/被观察者）的状态发生改变时，所有依赖于它的对象（观察者）都会收到通知并自动更新。&lt;/p&gt;
&lt;p&gt;观察者模式也被称为发布-订阅模式（Publish-Subscribe Pattern）。&lt;/p&gt;
&lt;h2 id="为什么需要观察者模式"&gt;为什么需要观察者模式&lt;/h2&gt;
&lt;p&gt;观察者模式要解决的核心问题是：&lt;strong&gt;当一个对象的状态发生变化时，如何自动通知所有依赖它的对象&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题场景&lt;/strong&gt;：假设我们正在开发一个电商App，用户登录后需要更新多个页面的状态（首页显示用户名、购物车同步、个人中心更新等）。&lt;/p&gt;
&lt;p&gt;最直接的方式可能是这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;LoginService&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;login&lt;/span&gt;(username: String, password: String) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 登录成功后...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; user = User(name: username)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 直接调用各个需要更新的对象&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HomeViewController.shared.updateUser(user)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; CartViewController.shared.syncCart(&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt;: user)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ProfileViewController.shared.refreshProfile(user)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 如果还有其他需要通知的地方，继续添加...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种方式有什么问题？&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;紧耦合&lt;/strong&gt;：LoginService必须知道所有需要通知的对象，依赖关系错综复杂&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;难以维护&lt;/strong&gt;：每新增一个需要监听登录事件的页面，都要修改LoginService&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;违反开闭原则&lt;/strong&gt;：对扩展不开放，每次扩展都要修改已有代码&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;单例滥用&lt;/strong&gt;：为了让LoginService能访问到各个页面，不得不使用大量单例&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;观察者模式的解决思路&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;被观察者（Subject）只负责&amp;quot;广播&amp;quot;状态变化，不关心谁在监听；观察者（Observer）自己注册感兴趣的事件：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 使用NotificationCenter实现&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;LoginService&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;login&lt;/span&gt;(username: String, password: String) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; user = User(name: username)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 只负责发送通知，不关心谁在监听&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NotificationCenter.&lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;.post(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: .userDidLogin,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; object: &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; userInfo: [&lt;span style="color:#e6db74"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;: user]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 各个页面自己注册监听&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;HomeViewController&lt;/span&gt;: UIViewController {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;viewDidLoad&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.viewDidLoad()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NotificationCenter.&lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;.addObserver(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; selector: &lt;span style="color:#66d9ef"&gt;#selector&lt;/span&gt;(handleUserLogin),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: .userDidLogin,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; object: &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;@objc&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;handleUserLogin&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; notification: Notification) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; user = notification.userInfo?[&lt;span style="color:#e6db74"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;] &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt;? User {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; updateUI(with: user)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;观察者模式的好处&lt;/strong&gt;：&lt;/p&gt;</description></item><item><title>设计模式概述</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E6%A6%82%E8%BF%B0/</link><pubDate>Wed, 27 May 2026 22:24:03 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E6%A6%82%E8%BF%B0/</guid><description>&lt;h2 id="什么是设计模式"&gt;什么是设计模式？&lt;/h2&gt;
&lt;p&gt;设计模式（Design Pattern）是软件开发中反复出现问题的经典解决方案。它们是前人在大量实践中总结出的、被证明有效的代码设计经验，可以帮助开发者编写出更加灵活、可维护、可复用的代码。&lt;/p&gt;
&lt;p&gt;设计模式不是具体的代码，而是解决特定问题的思想和模板。正确运用设计模式可以：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;提高代码的可读性和可维护性&lt;/li&gt;
&lt;li&gt;增强代码的可复用性&lt;/li&gt;
&lt;li&gt;降低模块间的耦合度&lt;/li&gt;
&lt;li&gt;提供通用的设计词汇，便于团队沟通&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="设计模式的起源"&gt;设计模式的起源&lt;/h2&gt;
&lt;p&gt;设计模式的概念最早由&amp;quot;四人帮&amp;quot;（Gang of Four，简称GoF）在1994年出版的《Design Patterns: Elements of Reusable Object-Oriented Software》一书中系统化提出。书中总结了23种经典设计模式，这些模式至今仍是软件设计的重要参考。&lt;/p&gt;
&lt;h2 id="设计模式分类"&gt;设计模式分类&lt;/h2&gt;
&lt;p&gt;GoF将23种设计模式分为三大类：&lt;/p&gt;
&lt;h3 id="创建型模式creational-patterns"&gt;创建型模式（Creational Patterns）&lt;/h3&gt;
&lt;p&gt;创建型模式关注对象的创建机制，旨在以合适的方式创建对象，而不是直接使用new操作符。这类模式使得代码在创建对象时更加灵活。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;模式&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;th&gt;iOS常见应用&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;单例模式&lt;/td&gt;
&lt;td&gt;确保一个类只有一个实例&lt;/td&gt;
&lt;td&gt;UIApplication.shared、FileManager.default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;工厂方法模式&lt;/td&gt;
&lt;td&gt;定义创建对象的接口，由子类决定实例化哪个类&lt;/td&gt;
&lt;td&gt;NSNumber的工厂方法&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;抽象工厂模式&lt;/td&gt;
&lt;td&gt;创建一系列相关对象而无需指定具体类&lt;/td&gt;
&lt;td&gt;UIKit组件创建&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;建造者模式&lt;/td&gt;
&lt;td&gt;将复杂对象的构建与表示分离&lt;/td&gt;
&lt;td&gt;URLComponents、AlertController&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;原型模式&lt;/td&gt;
&lt;td&gt;通过复制现有实例创建新对象&lt;/td&gt;
&lt;td&gt;NSCopying协议&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="结构型模式structural-patterns"&gt;结构型模式（Structural Patterns）&lt;/h3&gt;
&lt;p&gt;结构型模式关注类和对象的组合，用于形成更大的结构。这类模式帮助确保当系统的一部分发生改变时，整个系统不需要随之改变。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;模式&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;th&gt;iOS常见应用&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;适配器模式&lt;/td&gt;
&lt;td&gt;将一个类的接口转换成客户期望的另一个接口&lt;/td&gt;
&lt;td&gt;协议适配、第三方库封装&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;桥接模式&lt;/td&gt;
&lt;td&gt;将抽象部分与实现部分分离&lt;/td&gt;
&lt;td&gt;平台无关的抽象设计&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;组合模式&lt;/td&gt;
&lt;td&gt;将对象组合成树形结构以表示部分-整体层次结构&lt;/td&gt;
&lt;td&gt;UIView层级结构&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;装饰器模式&lt;/td&gt;
&lt;td&gt;通过包装对象在运行时动态添加职责&lt;/td&gt;
&lt;td&gt;包装器对象、链式装饰&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;外观模式&lt;/td&gt;
&lt;td&gt;为子系统提供一个统一的高层接口&lt;/td&gt;
&lt;td&gt;SDK封装、模块门面&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;享元模式&lt;/td&gt;
&lt;td&gt;运用共享技术有效支持大量细粒度对象&lt;/td&gt;
&lt;td&gt;字体对象、颜色对象等可共享的不可变对象&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;代理模式&lt;/td&gt;
&lt;td&gt;为其他对象提供一种代理以控制访问&lt;/td&gt;
&lt;td&gt;NSProxy、虚拟代理、保护代理&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="行为型模式behavioral-patterns"&gt;行为型模式（Behavioral Patterns）&lt;/h3&gt;
&lt;p&gt;行为型模式关注对象之间的通信和职责分配，描述类或对象如何交互以及如何分配职责。&lt;/p&gt;</description></item><item><title>责任链模式</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E8%B4%A3%E4%BB%BB%E9%93%BE%E6%A8%A1%E5%BC%8F/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E8%B4%A3%E4%BB%BB%E9%93%BE%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h2 id="定义"&gt;定义&lt;/h2&gt;
&lt;p&gt;责任链模式（Chain of Responsibility Pattern）是一种行为型设计模式，它将请求的发送者和接收者解耦，让多个对象都有机会处理请求。将这些对象连成一条链，并沿着这条链传递请求，直到有一个对象处理它为止。&lt;/p&gt;
&lt;p&gt;责任链模式的核心思想是：避免请求发送者与接收者耦合在一起，让多个对象都有可能接收请求，将这些对象组成一条链，并沿着这条链传递请求，直到有对象处理它为止。&lt;/p&gt;
&lt;h2 id="为什么需要责任链模式"&gt;为什么需要责任链模式&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;问题场景&lt;/strong&gt;：假设我们正在开发一个审批系统，不同金额的报销需要不同级别的人员审批。&lt;/p&gt;
&lt;p&gt;最直接的方式可能是这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ExpenseApproval&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;approve&lt;/span&gt;(amount: Double) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; amount &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 组长审批&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; teamLeaderApprove(amount)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; amount &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5000&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 部门经理审批&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; departmentManagerApprove(amount)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; amount &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10000&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 总监审批&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; directorApprove(amount)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// CEO审批&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ceoApprove(amount)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;teamLeaderApprove&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; amount: Double) { ... }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;departmentManagerApprove&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; amount: Double) { ... }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;directorApprove&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; amount: Double) { ... }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ceoApprove&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; amount: Double) { ... }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种方式有什么问题？&lt;/p&gt;</description></item><item><title>适配器模式</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F/</link><pubDate>Sun, 21 Jun 2026 22:41:52 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-design/patterns/%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h2 id="定义"&gt;定义&lt;/h2&gt;
&lt;p&gt;适配器模式（Adapter Pattern）是一种结构型设计模式，它将一个类的接口转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作。&lt;/p&gt;
&lt;p&gt;适配器模式的核心思想是：通过一个中间层（适配器）来使不兼容的接口能够一起工作，而无需修改原有代码。&lt;/p&gt;
&lt;h2 id="为什么需要适配器模式"&gt;为什么需要适配器模式&lt;/h2&gt;
&lt;p&gt;适配器模式要解决的核心问题是：&lt;strong&gt;让接口不兼容的类能够一起工作，而不需要修改原有代码&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题场景&lt;/strong&gt;：假设我们的App原来使用的是自己封装的网络库，现在想要切换到Alamofire，但项目中有大量地方直接使用了旧接口。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 旧的网络接口 - 项目中到处都在使用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;protocol&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;OldNetworkClient&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(url: String, callback: @escaping (Data?, Error?) -&amp;gt; Void)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;post&lt;/span&gt;(url: String, body: Data?, callback: @escaping (Data?, Error?) -&amp;gt; Void)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 新引入的Alamofire有完全不同的接口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// AF.request(url).response { response in ... }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最直接的方式是修改所有调用处：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 需要修改项目中所有使用旧接口的地方&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 从：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;oldClient.&lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;(url: &lt;span style="color:#e6db74"&gt;&amp;#34;https://api.example.com/users&amp;#34;&lt;/span&gt;) { data, error &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; ... }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 改为：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;AF.request(&lt;span style="color:#e6db74"&gt;&amp;#34;https://api.example.com/users&amp;#34;&lt;/span&gt;).response { response &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; ... }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种方式有什么问题？&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;工作量巨大&lt;/strong&gt;：需要修改项目中所有使用网络请求的地方&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;风险高&lt;/strong&gt;：大量修改容易引入bug&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;难以回退&lt;/strong&gt;：如果新库有问题，很难切换回旧实现&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;违反开闭原则&lt;/strong&gt;：修改了大量现有代码&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;适配器模式的解决思路&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;创建一个适配器，让新库&amp;quot;伪装&amp;quot;成旧接口，现有代码无需修改：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 适配器 - 让Alamofire适配旧接口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AlamofireAdapter&lt;/span&gt;: OldNetworkClient {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(url: String, callback: @escaping (Data?, Error?) -&amp;gt; Void) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 内部使用Alamofire，但对外暴露旧接口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; AF.request(url).response { response &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; callback(response.data, response.error)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;post&lt;/span&gt;(url: String, body: Data?, callback: @escaping (Data?, Error?) -&amp;gt; Void) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; AF.request(url, method: .post, parameters: &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;, encoding: URLEncoding.&lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .response { response &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; callback(response.data, response.error)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 现有代码完全不需要修改&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; client: OldNetworkClient = AlamofireAdapter()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;client.&lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;(url: &lt;span style="color:#e6db74"&gt;&amp;#34;https://api.example.com/users&amp;#34;&lt;/span&gt;) { data, error &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 原有的处理逻辑保持不变&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;适配器模式的好处&lt;/strong&gt;：&lt;/p&gt;</description></item></channel></rss>