iOS 设计模式的应用 ⑨ 中介者模式

前言

    在 App 中,我们常常遇到多个 UI 元素之间相互依赖,比如当列表框中的某一项被选中时,UILabel 会被更新为列表框中选定的值。又或者当用户在文本框输入了新的值时,需要将这个新的值加入到列表框的列表中。当更多的 UI 元素参与到这一错综复杂的关系之中时,情况可能变得难以控制,元素之间需要彼此了解并相互操作。又或者当从一个页面跳转到另一个页面时,需要了解目标页面所需参数等等。这个时候需要有一个集中化的角色组织各种 UI 元素在同一个语境下进行交互,称之为中介者(Mediator)

什么是中介者模式

    在面向对象的设计中鼓励把行为分散到不同对象中,这种分散可能导致对象之间的互相联系。在最糟糕的情况下,所有对象都彼此了解并相互操作。虽然把行为分散到不同对象增强了可复用性,但是增加的相互关联又减少了获得的益处。在这种情况下就需要中介者模式。中介者模式提供了一个中介类作为集中的场所,用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互

中介者模式的类图.png

什么时候使用中介者模式

  • 对象之间的交互虽然定义明确但是非常复杂,导致一组对象彼此相互依赖,形成了网状结构。若一个对象发生改变,我们也需要跟踪与之相关联的对象,同时做出相应的处理。
  • 对象引用了许多其它对象并与其通讯,导致对象难以复用
  • 想要定制一个分布在多个类中的逻辑或行为,又不想生成太多子类。

中介者模式的优缺点

中介者模式的优点

  1. 降低了类的复杂度,将一对多转化成了一对一。
  2. 各个类之间的解耦。
  3. 符合迪米特原则。(一个类对于其他类知道的越少越好)

中介者模式的缺点

随着系统规模的增大,中介者会越来越庞大,变得复杂难以维护。

Cocoa 中的中介者模式

    UIViewController是一个抽象类,可以对其进行子类化以管理特定视图。UIKit 框架还提供了UIViewController用于管理导航栏和工具栏对象的子类:UINavigationControllerUITabBarController. 一个 UITabController 可以管理多个 UINavigationController,而这些UINavigationController又可以管理一个或多个 UIViewController,每个控制器都有其关联的视图对象。除了管理视图(包括覆盖视图)之外,视图控制器还指定导航栏中显示的按钮和标题。

uictlr_object_diagram.jpeg

中介者模式的实现

运行时中介者模式的对象结构.png
  1. 定义中介者和对象遵守的协议

    @protocol Mediator;
    @protocol Colleague <NSObject>
    @property (nonatomic, strong) id <Mediator> mediator;
    - (void)receive;
    - (void)send;
    @end
      
    @protocol Mediator <NSObject>
    - (void)register:(id<Colleague>)colleague;
    - (void)relay:(id<Colleague>)cl;
    @end
    
    
  2. 实现其方法

    @interface ConcreteMediator : NSObject<Mediator>
    
    @end
    @interface ConcreteMediator ()
    @property (nonatomic, strong) NSMutableArray <id<Colleague>> *colleagues;
    @end
    @implementation ConcreteMediator
    - (NSMutableArray<id<Colleague>> *)colleagues{
        if (!_colleagues) {
            _colleagues = [NSMutableArray array];
        }
        return _colleagues;
    }
    - (void)register:(id<Colleague>)colleague{
        if ([colleague conformsToProtocol:@protocol(Colleague) ]){
            if(![self.colleagues containsObject:colleague]){
                [self.colleagues addObject:colleague];
                [colleague setMediator:self];
            }
        }
    }
    - (void)relay:(id<Colleague>)cl{
        for (id <Colleague> colleague  in self.colleagues) {
            if (![colleague isEqual:cl]) {
                [colleague  receive];
            }
        }
    }
    
    @end
    @interface ConcreteColleague1 : NSObject<Colleague>
    @end
    @implementation ConcreteColleague1
    
    @synthesize mediator;
    
    - (void)receive {
        NSLog(@"对象1收到消息");
    }
    
    - (void)send {
        NSLog(@"对象1发送消息");
        if (self.mediator) {
            [self.mediator relay:self];
        }
    }
    
    @end
    
    @interface ConcreteColleague2 : NSObject<Colleague>
    @end
    @implementation ConcreteColleague2
    @synthesize mediator;
    - (void)receive {
        NSLog(@"对象2收到消息");
    }
    - (void)send {
        NSLog(@"对象2发送消息");
        if (self.mediator) {
            [self.mediator relay:self];
        }
    }
    @end
    
  3. 最终调用对象方法时,会通过中介者进行管理、转发。

    ConcreteMediator *mediator = [ConcreteMediator new];
    ConcreteColleague1 *colleague1 = [[ConcreteColleague1 alloc] init];
    ConcreteColleague2 *colleague2 = [[ConcreteColleague2 alloc] init];
    
    [mediator register:colleague1];
    [mediator register:colleague2];
    [colleague1 send];
    [colleague2 send];
    

总结

    虽然对于处理应用程序行为分散到不同对象并且对象相互依存的情况,中介者模式非常有用,但是应当避免让中介者类过于庞大而难以维护。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容