ios開發-中介者模式

weixin_34075551發表於2018-02-05

簡介

在一個專案裡,程式由大量的類來組成。隨著功能的不斷增加,類和類之間的依賴關係也跟著趨於複雜,而中介者模式便能解決這個問題。
中介者模式,是用一個物件來封裝一組或一系列物件的互動方式,使物件間的互動可以在一箇中介者物件中處理,從而使各物件耦合鬆散,而且可以獨立的改變它們之間的互動。

中介者好比站在十字路口的交通警察。如果改變十字路口的交通模式,只需要把新的交通策略給交通警察即可,而不是路上的所有車輛,這樣才能更好的協調來自不同方向車輛。

好處

1、鬆散耦合

中介者模式通過把多個同事物件之間的互動封裝到中介物件裡面,從而使得同時物件之間鬆散耦合,基本上可以做到互不依賴。這樣一來,同時物件就可以獨立的變化和複用,不再“牽一髮動全身”。

2、集中控制互動

多個同事物件的互動,被封裝在中介者物件裡面集中管理,使得這些互動行為發生變化的時候,只需要修改中介者就可以了。

3、多對多變為一對多

沒有中介者模式的時候,同事物件之間的關係通常是多對多,引入中介者物件後,中介者和同事物件的關係通常變為雙向的一對多,這會讓物件的關係更容易理解和實現。

模式結構

6430368-d2905e3046ba1bbb.png
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。

傳統做法策略圖


6430368-ba8ff7786e09e46c.png
QQ.png

從圖中看到,這樣的處理方式繁亂複雜,不夠清晰,當控制器VC數量非常多時,更加難以維護。

中介者模式策略圖


6430368-70bb440336741597.png
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類的功能維護需要謹慎處理。

相關文章