设计模式面试题
适配器模式
定义 适配器模式(Adapter Pattern)是一种结构型设计模式,它将一个类的接口转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作。 适配器模式的核心思想是:通过一个中间层(适配器)来使不兼容的接口能够一起工作,而无需修改原有代码。 为什么需要适配器模式 适配器模式要解决的核心问题是:让接口不兼容的类能够一起工作,而不需要修改原有代码。 问题场景:假设我们的App原来使用的是自己封装的网络库,现在想要切换到Alamofire,但项目中有大量地方直接使用了旧接口。 // 旧的网络接口 - 项目中到处都在使用 protocol OldNetworkClient { func get(url: String, callback: @escaping (Data?, Error?) -> Void) func post(url: String, body: Data?, callback: @escaping (Data?, Error?) -> Void) } // 新引入的Alamofire有完全不同的接口 // AF.request(url).response { response in ... } 最直接的方式是修改所有调用处: // 需要修改项目中所有使用旧接口的地方 // 从: oldClient.get(url: "https://api.example.com/users") { data, error in ... } // 改为: AF.request("https://api.example.com/users").response { response in ... } 这种方式有什么问题? 工作量巨大:需要修改项目中所有使用网络请求的地方 风险高:大量修改容易引入bug 难以回退:如果新库有问题,很难切换回旧实现 违反开闭原则:修改了大量现有代码 适配器模式的解决思路: 创建一个适配器,让新库"伪装"成旧接口,现有代码无需修改: // 适配器 - 让Alamofire适配旧接口 class AlamofireAdapter: OldNetworkClient { func get(url: String, callback: @escaping (Data?, Error?) -> Void) { // 内部使用Alamofire,但对外暴露旧接口 AF.request(url).response { response in callback(response.data, response.error) } } func post(url: String, body: Data?, callback: @escaping (Data?, Error?) -> Void) { AF.request(url, method: .post, parameters: nil, encoding: URLEncoding.default) .response { response in callback(response.data, response.error) } } } // 现有代码完全不需要修改 let client: OldNetworkClient = AlamofireAdapter() client.get(url: "https://api.example.com/users") { data, error in // 原有的处理逻辑保持不变 } 适配器模式的好处: ...