1. 程式人生 > >設計模式深入淺出(六)物件去耦——中介者

設計模式深入淺出(六)物件去耦——中介者

物件去耦

我們的程式中,一般不會只有一個類,而通常是有多個類互相合作。

既然提到互相合作,那麼類物件間的耦合性是不可避免的。但是我們需要控制耦合的程度,將類的實現及關係控制在可以靈活改變的程度。

當我們發現我們的程式碼,牽一髮而動全身的時候,有兩個可能:
1. 類封裝的不合理,不符合職責單一原則
2. 類之間的組織方式不合理,需要物件去耦。而這,就需要物件去耦模式。

物件去耦主要包括兩種模式:中介者,觀察者。

今天,我們先看中介者模式。

一個例子

試想一下,我們要實現如下的APP功能,都是如何做的?

這個APP有一個colorView,用來顯示對應的color button點選的顏色。同時,colorLabel會顯示當前選中顏色的中文名稱。並且,我們有一個Disable按鈕,它會將所有的顏色選擇按鈕禁用,並將colorView設定為cleanColor。

這裡寫圖片描述

程式碼該怎麼寫?so easy。

//
//  ViewController.m
//  MediatorDemo
//
//  Created by ShiTeng on 17/10/16.
//  Copyright © 2017年 Eren. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@property (strong, nonatomic) IBOutlet UIView *colorView;

@property (strong, nonatomic) IBOutlet UILabel *colorLabel;
@property
(strong, nonatomic) IBOutlet UIButton *redButton; @property (strong, nonatomic) IBOutlet UIButton *greenButton; @property (strong, nonatomic) IBOutlet UIButton *orangeButton; @property (strong, nonatomic) IBOutlet UIButton *yellowButton; @end @implementation ViewController - (void)viewDidLoad { [super
viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (IBAction)redClick:(id)sender { self.colorView.backgroundColor = [UIColor redColor]; self.colorLabel.text = @"紅色"; } - (IBAction)greenClick:(id)sender { self.colorView.backgroundColor = [UIColor greenColor]; self.colorLabel.text = @"綠色"; } - (IBAction)orangeClick:(id)sender { self.colorView.backgroundColor = [UIColor orangeColor]; self.colorLabel.text = @"橘紅色"; } - (IBAction)yellowClick:(id)sender { self.colorView.backgroundColor = [UIColor yellowColor]; self.colorLabel.text = @"黃色"; } - (IBAction)disableClick:(id)sender { self.colorView.backgroundColor = [UIColor clearColor]; self.redButton.userInteractionEnabled = NO; self.greenButton.userInteractionEnabled = NO; self.orangeButton.userInteractionEnabled = NO; self.yellowButton.userInteractionEnabled = NO; self.colorLabel.text = @"未知"; } @end

好,讓我們思考這樣一個問題:毫無疑問,在我們的colorButton,colorView,colorLabel,disableButton之間,是有關聯的。比如,當我點選colorButton,colorView需要變色,同時colorLabel需要顯示對應的中文名字。

那麼,colorButton, colorView, colorLable之前有相互引用嗎?沒有。

從程式碼設計角度來講,很神奇是不是,幾個相互關聯的物件之間竟然沒有相互的引用。也就是說,colorButton根本不知道colorView,colorLabe的存在。colorButton只需要專注於相應click事件就好。

這是怎麼實現的呢?從程式碼裡很容易看出,我們的colorButton在接收click事件時,並沒有將事件直接通知給colorView和colorLabel,而是將click事件通知給了當前的UIViewController物件。同理,disableButton也是這麼做的。

- (IBAction)orangeClick:(id)sender {
    self.colorView.backgroundColor = [UIColor orangeColor];
    self.colorLabel.text = @"橘紅色";
}

- (IBAction)disableClick:(id)sender {
    self.colorView.backgroundColor = [UIColor clearColor];
    self.redButton.userInteractionEnabled = NO;
    self.greenButton.userInteractionEnabled = NO;
    self.orangeButton.userInteractionEnabled = NO;
    self.yellowButton.userInteractionEnabled = NO;
    self.colorLabel.text = @"未知";

}

將這種關係畫一下示意圖:
這裡寫圖片描述

所有的物件都沒有耦合,它們僅是將自己的事件告訴UIViewController,UIViewController會呼叫對應的View來響應變化。UIIViewController在這裡充當了各個view的中介(Mediator)的作用。

OK,這就是中介者模式。中介者模式通過將所有的事件轉發到中介者上,由中介者進行訊息的轉發與呼叫相關的物件進行處理,這樣使本來相關的各個物件徹底解耦

中介者模式

用一箇中介物件來封裝一系列的物件互動。中介者使各物件不需要顯示地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。

一般的,我們將相互作用的物件(例子中的colorButton,colorView,Label等)稱為“同事(colleague)”,而負責協調同事們共同協作的中間人(UIViewController),我們稱之為中介者(Mediator)。

UML圖為:
這裡寫圖片描述

這裡有幾個要點:

  • Mediator知道所有的Colleague物件
  • Colleague物件不知道對方Colleague,它僅是將自身的事件傳到Mediator,由Mediator負責排程對應的Colleague。

優缺點

優點:

  • 中介者的優點很明顯,將相關的物件之間做了徹底地解耦。
  • 它使得控制更集中化

缺點:

  • 中介者模式雖然將相關聯的物件徹底的解耦,但是實質上是將物件間的關聯由“物件間”轉移到“中介者”內部。這就導致中介者本身的耦合性相當高,而且會成為一個無所不知,無所不能的超級類。

如何簡化“中介者”,是中介者模式的一個難點。

相關的,iOS的元件化程式設計,也是利用了中介者模式的思想。將APP切分成若干子工程,而這些工程,則是由中介者工程所連線,協作。