ios开发-中介者模式

简介

在一个项目里,程序由大量的类来组成。随着功能的不断增加,类和类之间的依赖关系也跟着趋于复杂,而中介者模式便能解决这个问题。
中介者模式,是用一个对象来封装一组或一系列对象的交互方式,使对象间的交互可以在一个中介者对象中处理,从而使各对象耦合松散,而且可以独立的改变它们之间的交互。

中介者好比站在十字路口的交通警察。如果改变十字路口的交通模式,只需要把新的交通策略给交通警察即可,而不是路上的所有车辆,这样才能更好的协调来自不同方向车辆。

好处

1、松散耦合

中介者模式通过把多个同事对象之间的交互封装到中介对象里面,从而使得同时对象之间松散耦合,基本上可以做到互不依赖。这样一来,同时对象就可以独立的变化和复用,不再“牵一发动全身”。

2、集中控制交互

多个同事对象的交互,被封装在中介者对象里面集中管理,使得这些交互行为发生变化的时候,只需要修改中介者就可以了。

3、多对多变为一对多

没有中介者模式的时候,同事对象之间的关系通常是多对多,引入中介者对象后,中介者和同事对象的关系通常变为双向的一对多,这会让对象的关系更容易理解和实现。

模式结构

ios开发-中介者模式_第1张图片
QQ.png

1、Mediator:抽象中介者
在里面定义各个同事之间交互需要的方法,可以是公共的通信方法,也可以是小范围的交互方法。
2、ConcreteMeditor:具体中介者
它需要了解并维护各个同事对象,并负责具体的协调各同事对象的交互关系。
3、Colleague:抽象同事类
主要约束同事对象的类型,并实现一些具体同事类之间的公共功能,比如,每个具体同事类都应该知道中介者对象,也就是具体同事类都会持有中介者对象,都可以到这个类里面。
4、ConcreteColleague:具体同事类
实现自己的业务,需要与其他同事通信时候,就与持有的中介者通信,中介者会负责与其他同事类交互。

典型应用场景

  • MVC中的C(controller)就是一个中介者,它的作用就是把M和V隔离开,协调M和V协同工作,把M运行的结果和V代表的视图融合成一个前端可以展示的页面,减少M和V的依赖关系。

  • iOS中的UINavigationController就是一个中介者,他来管理视图的跳转。一般情况下,一个页面便对应代码中的一个VC,而一个中等规模的软件至少会有几十个的页面,对应的就是几十个VC。要管理这些VC之间的关系是一件非常繁琐的事情,每当一个VC要跳转到另外个VC,我们需要包含新的VC的头文件,于是有的起衔接作用的VC中包含了大量的其他VC的头文件。使用中介者模式可以非常好地去解决这个问题。

下面就以此为例,说明中介者模式的应用

应用——控制器切换

需求描述:在一个根视图控制器中(暂且称之为rootVC),点击不同的按钮,跳到对应的视图控制器,分别是firstVC、secondVC、thirdVC。

传统做法策略图


ios开发-中介者模式_第2张图片
QQ.png

从图中看到,这样的处理方式繁乱复杂,不够清晰,当控制器VC数量非常多时,更加难以维护。

中介者模式策略图


ios开发-中介者模式_第3张图片
QQ.png

从图中可以直观感受到,处理方式简洁明了。Mediator类的作用就相当于一个路由器,将客户发起的URL请求转移到对应的类。

下面来设计这个类

中介者Mediator类的设计

中介者,在应用程序整个生命周期应该只有一个实例,否则将无法管理多个对象间的交互,所以这里要使用单例来实现它的创建。这个过程就略过了,直接看重点部分。
首先添加2个控制器属性,一个表示用于发起跳转动作的控制器;另一个表示目的控制器。
在类的.h文件里,声明属性、方法。

@interface Mediator : NSObject

@property (nonatomic, strong, readonly) ViewController *rootVC;
@property (nonatomic, strong, readonly) UIViewController *activeVC;

//  单例创建类方法
+ (MediatorManager *)sharedManager;

//  外界跳转调用方法
- (void)jumpToNewViewController:(id)tagValue;

@end

在.m文件里面
导入所有需要跳转的控制器头文件

#import "ViewController.h"
#import "FirstViewController.h"
#import "SecondViewController.h"
#import "ThirdViewController.h"

实现跳转方法,根据传入的参数,决定跳转到哪个控制器VC

- (void)jumpToNewViewController:(id)tagValue{
    if ([tagValue isKindOfClass:[NSNumber class]]) {
        switch ([tagValue integerValue]) {
            case 1:
            {
                FirstViewController *firstVC = [[FirstViewController alloc] init];
                _activeVC = firstVC;
                [self.rootVC.navigationController pushViewController:firstVC animated:YES];
            }
                break;
            case 2:
            {
                SecondViewController *secondVC = [[SecondViewController alloc] init];
                _activeVC = secondVC;
                [self.rootVC.navigationController pushViewController:secondVC animated:YES];
            }
                break;
            case 3:
            {
                ThirdViewController *thirdVC = [[ThirdViewController alloc] init];
                _activeVC = thirdVC;
                [self.rootVC.navigationController pushViewController:thirdVC animated:YES];
            }
                break;
                
            default:    // 其他情况,默认返回
                _activeVC = self.rootVC;
                [self.rootVC.navigationController popViewControllerAnimated:YES];
                break;
        }
    }
}

这里,可以再优化一点,把各控制器VC对应标识符统一放在枚举变量里,方便管理。

typedef NS_ENUM(NSInteger, ButtonTag) {
    TagFirstVC  = 1,
    TagSecondVC = 2,
    TagThirdVC  = 3,
};

总结

中介者模式的应用不光用在VC的管理,当功能中出现了类似“多对多”的复杂的对象群时,就可以用到它来管理这些对象。
当然,在此之前,需要考虑的不应该是开始使用中介者模式,而是考虑这个功能的设计是否合理。
另外,使用中介者模式虽然降低了各个对象之间的耦合,减少了对象之间逻辑的复杂度,但是这个复杂度在一定程度上转移到了Mediator类中,因此Mediator类的功能维护需要谨慎处理。

你可能感兴趣的