Objective-C 类的协议(Protocol)应用:解耦父子类与跨类通信实践

Objective-C 协议(Protocol)应用:解耦父子类与跨类通信实践

在 Objective-C 中,协议(Protocol)是一种强大的解耦工具,特别适用于以下场景:

  1. 解耦父子类继承关系
    避免通过继承强制共享方法实现
  2. 跨类通信
    实现对象间松耦合的交互

一、协议解耦父子类实践

场景:父类需要调用子类特定功能,但不强制所有子类实现

  1. 定义协议

    objectivec 复制代码
    @protocol DataProcessor <NSObject>
    - (NSString *)processData:(NSData *)rawData;
    @optional
    - (void)logProcessingResult;
    @end
  2. 父类使用协议

    objectivec 复制代码
    @interface BaseViewController : UIViewController
    @property (nonatomic, weak) id<DataProcessor> processor;
    - (void)handleData:(NSData *)data;
    @end
    
    @implementation BaseViewController
    - (void)handleData:(NSData *)data {
        if ([self.processor respondsToSelector:@selector(processData:)]) {
            NSString *result = [self.processor processData:data];
            NSLog(@"处理结果: %@", result);
            
            // 可选方法检查
            if ([self.processor respondsToSelector:@selector(logProcessingResult)]) {
                [self.processor logProcessingResult];
            }
        }
    }
    @end
  3. 子类选择性实现

    objectivec 复制代码
    @interface ImageProcessor : BaseViewController <DataProcessor>
    @end
    
    @implementation ImageProcessor
    - (NSString *)processData:(NSData *)rawData {
        return @"图片处理完成";
    }
    // 可选方法不实现
    @end

优势

  • 子类无需继承无用方法
  • 父类不依赖具体子类实现
  • 支持多态:任意遵守协议的对象都可作为processor

二、跨类通信实践(委托模式)

场景:网络模块完成下载后通知UI更新

  1. 定义通信协议

    objectivec 复制代码
    @protocol DownloadDelegate <NSObject>
    - (void)downloadDidComplete:(NSURL *)filePath;
    - (void)downloadFailedWithError:(NSError *)error;
    @end
  2. 服务类持有委托

    objectivec 复制代码
    @interface DownloadManager : NSObject
    @property (nonatomic, weak) id<DownloadDelegate> delegate;
    - (void)startDownload:(NSURL *)url;
    @end
    
    @implementation DownloadManager
    - (void)startDownload:(NSURL *)url {
        // 模拟下载完成
        [self.delegate downloadDidComplete:url];
    }
    @end
  3. UI类实现协议

    objectivec 复制代码
    @interface ProfileViewController : UIViewController <DownloadDelegate>
    @property (nonatomic, strong) DownloadManager *downloader;
    @end
    
    @implementation ProfileViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.downloader = [DownloadManager new];
        self.downloader.delegate = self; // 建立连接
        [self.downloader startDownload:[NSURL URLWithString:@"https://example.com/avatar.jpg"]];
    }
    
    #pragma mark - DownloadDelegate
    - (void)downloadDidComplete:(NSURL *)filePath {
        [self updateAvatarWithImage:[UIImage imageWithContentsOfFile:filePath.path]];
    }
    @end

三、关键实践原则
  1. 弱引用委托

    始终使用 weak 属性避免循环引用:
    @property (nonatomic, weak) id<MyProtocol> delegate;

  2. 可选方法标记

    @optional 声明非必需方法,调用前检查响应:

    objectivec 复制代码
    if ([delegate respondsToSelector:@selector(optionalMethod)]) {
        [delegate optionalMethod];
    }
  3. 协议组合替代继承

    类可遵循多个协议实现不同能力:

    objectivec 复制代码
    @interface MyClass : NSObject <ProtocolA, ProtocolB>
  4. 类型安全校验

    运行时检查协议一致性:

    objectivec 复制代码
    if ([someObject conformsToProtocol:@protocol(RequiredProtocol)]) {
        // 安全调用
    }

四、优势总结
场景 传统方案问题 协议方案优势
父子类通信 父类需知晓子类具体类型 父类只依赖协议接口
模块间通信 直接引用导致紧耦合 通过委托实现间接松耦合
功能扩展 需修改基类 新增协议不影响现有实现

通过协议实现: $$ \text{解耦度} \propto \frac{1}{\text{类间直接依赖}} $$ 有效降低代码耦合度,提升模块复用性和可测试性。

相关推荐
心灵宝贝12 小时前
Mac 安装 JDK 8u281(JDK-8u281-1.dmg)详细步骤(附安装包)
java·macos·intellij-idea
拾忆,想起12 小时前
Dubbo超时问题排查与调优指南:从根因到解决方案
服务器·开发语言·网络·微服务·架构·php·dubbo
7ioik12 小时前
什么是线程池?线程池的作用?线程池的四种创建方法?
java·开发语言·spring
寻星探路13 小时前
JavaSE重点总结后篇
java·开发语言·算法
Charles_go14 小时前
C#中级8、什么是缓存
开发语言·缓存·c#
松涛和鸣15 小时前
14、C 语言进阶:函数指针、typedef、二级指针、const 指针
c语言·开发语言·算法·排序算法·学习方法
智商低情商凑19 小时前
Go学习之 - Goroutines和channels
开发语言·学习·golang
半桶水专家19 小时前
Go 语言时间处理(time 包)详解
开发语言·后端·golang
编程点滴19 小时前
Go 重试机制终极指南:基于 go-retry 打造可靠容错系统
开发语言·后端·golang
Q***l68719 小时前
后端服务网格可观测性,Jaeger追踪可观测性实践:Jaeger追踪详解
spring cloud·objective-c·p2p