Swift设计模式:从理论到实践
设计模式是开发中常见问题的成熟解决方案。对于使用Swift的iOS开发者来说,掌握设计模式不仅是简历上的加分项,更是必备技能。它们有助于编写干净、可复用且可测试的代码。本文将结合实际Swift示例,解析5种关键模式。
1. 单例模式
iOS中最流行的模式之一。它确保类只有一个实例,并提供全局访问点。
Swift实现
class NetworkManager { static let shared = NetworkManager() private init() {} // 防止创建其他实例
func requestData(from url: URL) { // 请求逻辑 print("请求 \\(url.absoluteString)") }}
// 使用NetworkManager.shared.requestData(from: URL(string: "https://api.example.com")!)使用场景:管理共享资源(网络、数据库、UserDefaults)。缺点:增加单元测试复杂度,不宜滥用。
2. 工厂方法
定义创建对象的接口,但让子类决定实例化哪个具体类。当不确定需要哪种具体对象时非常适用。
示例:创建UI元素
protocol Button { func render()}
class iOSButton: Button { func render() { print("iOS风格按钮") }}
class macOSButton: Button { func render() { print("macOS风格按钮") }}
enum Platform { case iOS, macOS}
class ButtonFactory { static func createButton(for platform: Platform) -> Button { switch platform { case .iOS: return iOSButton() case .macOS: return macOSButton() } }}
// 使用let button = ButtonFactory.createButton(for: .iOS)button.render() // iOS风格按钮3. 观察者模式
允许对象订阅事件并接收变更通知。在Swift中,通过NotificationCenter和Combine原生实现。
使用NotificationCenter示例
extension Notification.Name { static let userDidLogin = Notification.Name("userDidLogin")}
class AuthManager { func login() { // 登录逻辑 NotificationCenter.default.post(name: .userDidLogin, object: nil) }}
class ProfileViewController { init() { NotificationCenter.default.addObserver( self, selector: #selector(updateUI), name: .userDidLogin, object: nil ) }
@objc func updateUI() { print("登录后更新个人资料") }
deinit { NotificationCenter.default.removeObserver(self) }}现代替代方案:使用Combine(iOS 13+)配合@Published和PassthroughSubject进行响应式编程。
4. 委托模式
Cocoa Touch的基础模式之一。允许一个对象将任务执行委托给另一个对象。广泛应用于UIKit(如UITableViewDelegate)。
创建自定义委托
protocol DownloadDelegate: AnyObject { func didFinishDownloading(data: Data) func didFailWithError(error: Error)}
class Downloader { weak var delegate: DownloadDelegate?
func download(from url: URL) { // 模拟下载 let data = Data() delegate?.didFinishDownloading(data: data) }}
class ViewController: UIViewController, DownloadDelegate { let downloader = Downloader()
override fu