iOS设计模式-适配器

思想

本质是 把一个"接口不兼容"的对象,转换成你当前系统期望的接口,从而进行调用。

------将一个类的接口,转换成客户端期望的接口,使原本不兼容的类可以协同工作。

------在两个不兼容的接口之间架一座"桥",让原本无法协作的类可以一起工作,而不必修改原有代码。

可以理解为"中间翻译层"。

总结来说,适配器模式用于解决接口不兼容的问题,通过适配器将不兼容的接口转换为兼容的接口,从而使得不同的类能够一起工作。

三个角色

适配者:具有原始接口的类

抽象接口:客户端期望的接口形式

适配器:封装,转发调用

应用场景

常用于集成/调用 第三方 SDK、适配旧代码、数据模型适配。

"旧代码 / 第三方库 / 不同结构的数据 → 统一成我当前代码能用的样子"

应用一: 第三方 SDK的二次封装

你接入了一个第三方 SDK,它的接口不符合你当前项目的设计规范(比如命名、回调方式不同)。即使规范,原则上也不要直接依赖,直接调用其接口。

swift 复制代码
class ThirdPartyAudioSDK { 
    // 播放
    func loadAndPlay(path: String, volume: Float) {
        print("SDK 播放: \(path) 音量: \(volume)") 
    } 
}
  • 一般调用方式,直接依赖SDK类
scss 复制代码
class VC { 
    func do(){
        let sdk = ThirdPartyAudioSDK()
        sdk.loadAndPlay()
    }
}

采用适配器模式,对SDK进行包装

1、设计抽象协议(接口)

swift 复制代码
protocol AudioPlayer { 
    func play(file: String) 
}

2、设计适配器类

遵循协议,持有SDK对象。实质:调用转发

swift 复制代码
class AudioPlayerAdapter: AudioPlayer {
    private let sdk = ThirdPartyAudioSDK()

    func play(file: String) {
        // 转换调用:适配接口差异
        sdk.loadAndPlay(path: "/media/\(file)", volume: 1.0)
    }
}

业务调用

php 复制代码
class VC {
    func playMusic(player: AudioPlayer) {
        player.play(file: "song.mp3")
    }
}

self.playMusic(player: AudioPlayerAdapter())

这样就实现了解耦,业务代码只依赖 AudioPlayer 协议,不知道内部用的是第三方 SDK。

好处:可灵活更换SDK;不污染业务代码。

应用二:服务器数据 的封装

服务端返回的JSON数据,最好不要直接读取使用。原因:

  • 避免耦合
  • 字段名不规范/适合
  • 不是所有字段都显示在UI上
  • 需要进行数据转换/预处理
json 复制代码
{
    "num": 1,
    "is_expire": 0,
    "reward_content": "10",
    "reward_name": "WSpoint_reward",
    "reward_type": 1,
    "sign_state": 3,
    "sign_time": 0,
    "trigger_type": 1
}

解析

rust 复制代码
struct UserDTO: Decodable {
    let sign_time: String
    let trigger_type: Int
    ....
}

采用适配器模式,对服务端返回的数据进行封装

1、设计抽象协议

涵盖 业务层需要用到的数据,及 UI层可直接展示的数据

如:

kotlin 复制代码
protocol UIDataDisplay { 
    var count: Int { get }
    var name: String { get }
    .....
}

2、设计适配器类

kotlin 复制代码
class ModelAdater: UIDataDisplay {
    let json: UserDTO
    
    var num: Int
    var type: Int
    ...

    init(json: UserDTO){
        self.num = json.num
        ...
    }
    
    // 实现抽象属性
    var count: Int {
        return json.num
    }
    
    var name: String { 
        return json.firstName + json.secondName
    }
}

3、UI 与 具体数据类型 解耦

swift 复制代码
class Cell {
    func config(model: UIDataDisplay){
        self.nameLabel.text = model.name
        ...
    }
}

好处

  • 数据集中在Adapter进行处理
  • 解耦 UI 和数据结构
  • 扩展性,后端字段变了 → 只改 Adapter
相关推荐
漂流瓶jz30 分钟前
理解Webpack插件机制:从插件使用、各类编译对象、Tapable到自定义插件与钩子开发
前端·javascript·webpack
梦帮科技11 小时前
GRAVIS v4.0:基于Web的极速套利架构设计与实时数据流实现
前端·人工智能·rust·自动化·区块链·智能合约·数字货币
爱勇宝11 小时前
办公资料反复修改、补传、交接混乱,我做了个桌面工具来解决这件事
前端·后端·程序员
微信开发api-视频号协议12 小时前
企业微信外部群开发自动化实践过程
java·前端·微信·自动化·企业微信·ipad
甲维斯12 小时前
Fable5:20美金的顶级设计师!
前端·人工智能
kyriewen12 小时前
我同时用了 Claude Code、Cursor 和 Codex,说说三个工具的真实差距——2026 年选错工具比不用 AI 更浪费时间
前端·ai编程·claude
Jackson__13 小时前
为了拯救我的腰椎和颈椎,我做了款浏览器插件!
前端·javascript·开源
闲猫13 小时前
Python FastAPI + SQLAlchemy 入门教程:从零搭建你的第一个 Web 应用
前端·python·fastapi
林小帅13 小时前
NestJS v11 + Prisma v7 ESM 迁移配置解析
前端·javascript·后端
IT_陈寒13 小时前
React的setState竟然不是立刻生效的,害我调试半天
前端·人工智能·后端