iOS中,组件化和模块化的区别是什么?如何实现组件间通信?代码案例

一、iOS 中组件化与模块化的区别


1. 定义与核心目标

特性

模块化(Modularization)

组件化(Componentization)



2. 典型场景


• 模块化:将项目拆分为 NetworkModule、UtilsModule、BaseUIKit 等,模块间通过头文件引用通信。


• 组件化:将电商 App 拆分为 HomeComponent、GoodsComponent、CartComponent,每个组件可独立运行,通过路由跳转。


二、组件间通信的实现方式


组件化的核心挑战是解耦组件依赖,常见通信方式如下:


1. 基于协议/代理(Protocol/Delegate)


适用场景:单向通信(如 A 组件调用 B 组件的某个功能)。

优点:强类型约束,编译期检查;缺点:组件间需引入协议头文件,存在间接依赖。


代码案例(Objective-C)


• 定义公共协议(跨组件接口)

// 公共协议(通常放在基础库或中间件中)

@protocol CartComponentProtocol <NSObject>

- (void)showCartViewController; // 展示购物车页面

@end

• B 组件(购物车组件)实现协议

// CartViewController.h

@interface CartViewController : UIViewController <CartComponentProtocol>

- (void)showCartViewController {

    // 展示购物车逻辑

}

@end

• A 组件(首页组件)通过协议调用

// HomeViewController.m

@property (nonatomic, weak) id<CartComponentProtocol> cartDelegate; // 弱引用代理


// 触发通信

[self.cartDelegate showCartViewController];

2. 通知中心(NSNotification / NotificationCenter)


适用场景:一对多广播通信(如全局状态变更通知)。

优点:组件间无直接依赖;缺点:弱类型,运行时风险,难以追踪调用链。


代码案例(Swift)


• B 组件(接收通知)

// CartComponent.swift

NotificationCenter.default.addObserver(

    self,

    selector: #selector(updateCartBadge),

    name: NSNotification.Name("UpdateCartBadge"),

    object: nil

)


@objc func updateCartBadge(notification: NSNotification) {

    guard let count = notification.userInfo?["count"] as? Int else { return }

    // 更新购物车角标

}

• A 组件(发送通知)

// HomeComponent.swift

NotificationCenter.default.post(

    name: NSNotification.Name("UpdateCartBadge"),

    object: nil,

    userInfo: ["count": 5]

)

3. 路由机制(Router Pattern)


适用场景:复杂组件间跳转、参数传递(如页面跳转、服务调用)。

核心思想:通过统一的路由中心,用字符串标识(如 URL 或组件名)映射到具体组件,避免直接依赖。


实现步骤:


1. 定义路由中心(Router)

// Router.h(Objective-C)

@interface Router : NSObject

+ (instancetype)shared;

// 注册组件:将 URL 或组件名映射到类/方法

- (void)registerURLPattern:(NSString *)pattern toClass:(Class)cls;

// 路由跳转:通过 URL 或组件名调用组件功能

- (UIViewController *)openURL:(NSString *)url withParams:(NSDictionary *)params;

@end


// Router.swift(Swift)

class Router {

    static let shared = Router()

    private var routeMap = [String: AnyClass]() // URL 到类的映射

   

    func register(urlPattern: String, to cls: AnyClass) {

        routeMap[urlPattern] = cls

    }

   

    func open(url: String, params: [String: Any] = [:]) -> UIViewController? {

        guard let cls = routeMap[url] as? UIViewController.Type else { return nil }

        let vc = cls.init()

        // 传递参数(需约定参数协议)

        if let paramsVC = vc as? RouteParamsHandler {

            paramsVC.handle(params: params)

        }

        return vc

    }

}

2. 组件注册路由


购物车组件注册页面路由

// CartComponent.m

+ (void)load {

    [[Router shared] registerURLPattern:@"cart://show" toClass:[CartViewController class]];

}

3. 跨组件调用


首页组件通过路由打开购物车

// HomeComponent.m

UIViewController *cartVC = [[Router shared] openURL:@"cart://show" withParams:@{@"userId": @"123"}];

[self.navigationController pushViewController:cartVC animated:YES];

4. 中间件模式(Protocol + 工厂类)


适用场景:组件需暴露复杂服务(如获取数据、操作功能)。

实现:定义中间件协议,组件实现协议,通过工厂类获取实例。


代码案例(Objective-C)


• 定义中间件协议

// UserServiceProtocol.h

@protocol UserServiceProtocol <NSObject>

- (NSString *)getCurrentUserName;

- (void)logout;

@end

• 用户组件实现协议

// UserService.m

@interface UserService : NSObject <UserServiceProtocol>

- (NSString *)getCurrentUserName { return @"张三"; }

- (void)logout { /* 登出逻辑 */ }

@end

• 工厂类获取服务

// ServiceFactory.h

+ (id<UserServiceProtocol>)getUserService {

    // 动态加载用户组件(如通过运行时或配置文件)

    return [[UserService alloc] init];

}

三、组件化实战:路由跳转案例(Objective-C)


1. 组件结构

Project

├─ BaseComponent  // 基础库(含路由中心、公共协议)

├─ HomeComponent  // 首页组件(Target: HomeModule)

├─ CartComponent  // 购物车组件(Target: CartModule)

└─ AppDelegate    // 主工程

2. 路由中心实现(BaseComponent/Router.h)

#import <UIKit/UIKit.h>


@protocol RouteParamsHandler <NSObject>

- (void)handleRouteParams:(NSDictionary *)params;

@end


@interface Router : NSObject

+ (instancetype)shared;

- (void)registerURL:(NSString *)url toViewControllerClass:(Class)vcClass;

- (UIViewController *)openURL:(NSString *)url withParams:(NSDictionary *)params;

@end

3. 购物车组件注册路由(CartComponent/CartViewController.m)

#import "CartViewController.h"

#import "Router.h"


@implementation CartViewController


+ (void)load {

    // 组件加载时注册路由(利用 +load 方法自动执行)

    [[Router shared] registerURL:@"cart://view" toViewControllerClass:self.class];

}


- (void)handleRouteParams:(NSDictionary *)params {

    self.userId = params[@"userId"]; // 接收参数

}


@end

4. 首页组件触发路由跳转(HomeComponent/HomeViewController.m)

#import "HomeViewController.h"

#import "Router.h"


- (IBAction)goToCartButtonTapped:(id)sender {

    UIViewController *cartVC = [[Router shared] openURL:@"cart://view" withParams:@{@"userId": @"123"}];

    [self.navigationController pushViewController:cartVC animated:YES];

}

5. 路由中心实现细节(BaseComponent/Router.m)

#import "Router.h"


@interface Router ()

@property (nonatomic, strong) NSMutableDictionary<NSString *, Class> *routeMap;

@end


@implementation Router


+ (instancetype)shared {

    static dispatch_once_t onceToken;

    static Router *instance;

    dispatch_once(&onceToken, ^{

        instance = [[Router alloc] init];

    });

    return instance;

}


- (void)registerURL:(NSString *)url toViewControllerClass:(Class)vcClass {

    self.routeMap[url] = vcClass;

}


- (UIViewController *)openURL:(NSString *)url withParams:(NSDictionary *)params {

    Class vcClass = self.routeMap[url];

    if (!vcClass) {

        NSLog(@"未找到路由:%@", url);

        return nil;

    }

    UIViewController *vc = [[vcClass alloc] init];

    if ([vc respondsToSelector:@selector(handleRouteParams:)]) {

        [vc performSelector:@selector(handleRouteParams:) withObject:params];

    }

    return vc;

}


@end

四、总结


1. 核心区别:


模块化是“分而治之”,解决代码复用;组件化是“独立自治”,解决复杂业务解耦与团队协作。


2. 通信选择:


简单场景用 协议/代理 或 通知;


复杂场景(如页面跳转、跨组件服务调用)用 路由机制(推荐,解耦最彻底)。


3. 最佳实践:


定义统一的中间件协议或路由规范,避免组件直接依赖;


利用 +load 或初始化方法自动注册组件路由,减少手动配置。


通过组件化与路由机制,可实现“组件独立开发、动态组装”,大幅提升大型项目的可维护性与协作效率。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容