問題:
在軟件的開發(fā)過程中,勢(shì)必會(huì)碰到這樣一種情況,多個(gè)類或多個(gè)子系統(tǒng)相互交互,而且交互很繁瑣,導(dǎo)致每個(gè)類都必須知道他需要交互的類,這樣它們的耦合會(huì)顯得異常厲害。牽一發(fā)而動(dòng)全身,
好了,既然問題提出來了,那有請(qǐng)我們這期的主角——中介者模式出場(chǎng)吧!
中介者模式
用一個(gè)中介者對(duì)象來封裝一系列的對(duì)象交互。中介者使得各對(duì)象不需要顯式地相互引用,從而使其松散耦合,而且可以獨(dú)立地改變它們之間的交互。
中介者模式結(jié)構(gòu)圖
例子(oc版):
#import <UIKit/UIKit.h>
@interface DPMredViewController : UIViewController
@end
#import "DPMredViewController.h"
#import "DPMediator.h"
@interface DPMredViewController ()
@end
@implementation DPMredViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor redColor];
self.title = @"我是紅色控制器";
[self setupUI];
}
- (void)setupUI{
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
button.backgroundColor = [UIColor blackColor];
button.frame = CGRectMake(self.view.bounds.size.width/2-30, self.view.bounds.size.height/2-30, 60, 60);
[button addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside];
button.layer.cornerRadius = 30;
button.layer.masksToBounds = YES;
[button setTitle:@"下一個(gè)" forState:UIControlStateNormal];
[self.view addSubview:button];
}
- (void)clickButton:(UIButton *)sender{
[[DPMediator shareInstance] requestNextViewControllerWithType:greenVCType];
}
@end
#import <UIKit/UIKit.h>
@interface DPMgreenViewController : UIViewController
@end
#import "DPMgreenViewController.h"
#import "DPMediator.h"
@interface DPMgreenViewController ()
@end
@implementation DPMgreenViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor greenColor];
self.title = @"我是綠色控制器";
[self setupUI];
}
- (void)setupUI{
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
button.backgroundColor = [UIColor blackColor];
button.frame = CGRectMake(self.view.bounds.size.width/2-30, self.view.bounds.size.height/2-30, 60, 60);
[button addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside];
button.layer.cornerRadius = 30;
button.layer.masksToBounds = YES;
[button setTitle:@"下一個(gè)" forState:UIControlStateNormal];
[self.view addSubview:button];
}
- (void)clickButton:(UIButton *)sender{
[[DPMediator shareInstance] requestNextViewControllerWithType:blueVCType];
}
@end
#import <UIKit/UIKit.h>
@interface DPMblueViewController : UIViewController
@end
#import "DPMblueViewController.h"
#import "DPMediator.h"
@interface DPMblueViewController ()
@end
@implementation DPMblueViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor blueColor];
self.title = @"我是藍(lán)色控制器";
[self setupUI];
}
- (void)setupUI{
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
button.backgroundColor = [UIColor blackColor];
button.frame = CGRectMake(self.view.bounds.size.width/2-30, self.view.bounds.size.height/2-30, 60, 60);
[button addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside];
button.layer.cornerRadius = 30;
button.layer.masksToBounds = YES;
[button setTitle:@"下一個(gè)" forState:UIControlStateNormal];
[self.view addSubview:button];
}
- (void)clickButton:(UIButton *)sender{
[[DPMediator shareInstance] requestNextViewControllerWithType:defaultVCType];
}
@end
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger, VCType) {
defaultVCType,
redVCType,
greenVCType,
blueVCType
};
@interface DPMediator : NSObject
+ (DPMediator *)shareInstance;
- (void)requestNextViewControllerWithType:(VCType) vctype;
@end
#import "DPMediator.h"
#import "AppDelegate.h"
#import "DPMredViewController.h"
#import "DPMgreenViewController.h"
#import "DPMblueViewController.h"
@interface DPMediator()
@end
@implementation DPMediator
+ (DPMediator *)shareInstance{
static DPMediator * instance = nil;
static dispatch_once_t tokeOnce;
dispatch_once(&tokeOnce, ^{
instance = [[DPMediator alloc] init];
});
return instance;
}
- (void)requestNextViewControllerWithType:(VCType) vctype{
UIViewController * viewController = [UIApplication sharedApplication].keyWindow.rootViewController.childViewControllers.lastObject;
switch (vctype) {
case redVCType:
{
DPMredViewController * vc = [[DPMredViewController alloc] init];
[viewController.navigationController pushViewController:vc animated:YES];
}
break;
case greenVCType:
{
DPMgreenViewController * vc = [[DPMgreenViewController alloc] init];
[viewController.navigationController pushViewController:vc animated:YES];
}
break;
case blueVCType:
{
DPMblueViewController * vc = [[DPMblueViewController alloc] init];
[viewController.navigationController pushViewController:vc animated:YES];
}
break;
case defaultVCType:
{
[viewController.navigationController popToRootViewControllerAnimated:YES];
}
break;
default:
break;
}
}
@end
//開始使用
#import "DPMmainViewController.h"
#import "DPMediator.h"
#import "DPMediatorWithC++Show.h"
@interface DPMmainViewController ()
@end
@implementation DPMmainViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
// Do any additional setup after loading the view.
self.title = @"中介者模式";
[self setupUI];
}
- (void)setupUI{
UIButton * button1 = [UIButton buttonWithType:UIButtonTypeCustom];
[button1 setTitle:@"oc版" forState:UIControlStateNormal];
button1.frame = CGRectMake(30, 200, 60, 60);
button1.backgroundColor = [UIColor redColor];
button1.layer.cornerRadius = 30;
button1.layer.masksToBounds = YES;
[button1 addTarget:self action:@selector(clickOCButton:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button1];
UIButton * button2 = [UIButton buttonWithType:UIButtonTypeCustom];
[button2 setTitle:@"c++版" forState:UIControlStateNormal];
button2.frame = CGRectMake(self.view.bounds.size.width-30-60, 200, 60, 60);
button2.backgroundColor = [UIColor redColor];
button2.layer.cornerRadius = 30;
button2.layer.masksToBounds = YES;
[button2 addTarget:self action:@selector(clickCCButton:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button2];
}
- (void)clickOCButton:(UIButton *)sender{
[[DPMediator shareInstance] requestNextViewControllerWithType:redVCType];
}
@end
例子(C++版):
#include <iostream>
#include <vector>
#include <string>
using namespace std;
//抽象的同事類
class Colleage{
private:
string name;
string content;
public:
Colleage(string n = " "):name(n){};
void setName(string name){
this->name = name;
}
string getName(){
return this->name;
}
void setContent(string content){
this->content = content;
}
string getContent(){
return this->content;
}
virtual void talk() {};
};
// 具體的同事類:班長(zhǎng)
class Monitor : public Colleage{
public:
Monitor(string n = ""): Colleage(n){};
virtual void talk(){
cout<<"大班長(zhǎng)說:"<<getContent()<<endl;
}
};
//具體的同事類:團(tuán)支書
class TuanZhiShu: public Colleage{
public:
TuanZhiShu(string n = " "): Colleage(n){};
virtual void talk (){
cout<<"團(tuán)支書說:"<<getContent()<<endl;
}
};
//具體的同事類:同學(xué)A
class StudentA: public Colleage{
public:
StudentA(string n = ""):Colleage(n){};
virtual void talk(){
cout<<"學(xué)生A說:"<<getContent()<<endl;
}
};
//具體的同事類:同學(xué)B
class StudentB : public Colleage{
public:
StudentB(string n = ""): Colleage(n){};
virtual void talk(){
cout << "同學(xué)B說:"<<getContent()<<endl;
}
};
//抽象中介者
class Mediator{
public:
vector<Colleage *> studentList;
virtual void addStudent(Colleage * student){
studentList.push_back(student);
}
virtual void notify(Colleage * student){};
virtual void chart(Colleage * student1, Colleage * student2) {};
};
//具體中介者QQ通訊平臺(tái)
class QQMediator : public Mediator{
public:
virtual void notify(Colleage * student){
student->talk();
for (int i =0; i<studentList.size(); i++) {
if (student != studentList[i]) {
studentList[i]->talk();
}
}
}
virtual void chart(Colleage * student1, Colleage * student2){
student1->talk();
student2->talk();
}
};
//使用
- (void)clickCCButton:(UIButton *)sender{
QQMediator qq;
Monitor studentMonitor("Vincent");
TuanZhiShu studentTuanZhiShu("Robort");
StudentA studentA("Sam");
StudentB studentB("Tom");
cout<<"下面的班長(zhǎng)發(fā)布一個(gè)通知的場(chǎng)景:"<<endl;
//將同學(xué)們加入到qq群中
qq.addStudent(&studentMonitor);
qq.addStudent(&studentTuanZhiShu);
qq.addStudent(&studentA);
qq.addStudent(&studentB);
//設(shè)置大家的回復(fù)消息
studentMonitor.setContent("明天下午2點(diǎn)開年紀(jì)會(huì),收到回復(fù)");
studentTuanZhiShu.setContent("知道了,肯定到");
studentA.setContent("收到了,但是可能晚點(diǎn)到");
studentB.setContent("收到了,但是明天考試");
//開始發(fā)通知
qq.notify(&studentMonitor);
cout<<endl<<"下面是兩個(gè)同學(xué)的私下交流"<<endl;
studentMonitor.setContent("你覺得我們的老師怎么樣");
studentA.setContent("我覺得不好");
qq.chart(&studentMonitor, &studentA);
}
下面的班長(zhǎng)發(fā)布一個(gè)通知的場(chǎng)景:
大班長(zhǎng)說:明天下午2點(diǎn)開年紀(jì)會(huì),收到回復(fù)
團(tuán)支書說:知道了,肯定到
學(xué)生A說:收到了,但是可能晚點(diǎn)到
同學(xué)B說:收到了,但是明天考試
下面是兩個(gè)同學(xué)的私下交流
大班長(zhǎng)說:你覺得我們的老師怎么樣
學(xué)生A說:我覺得不好
總結(jié):
中介者模式很容易在系統(tǒng)中應(yīng)用,也很容易在系統(tǒng)中誤用。當(dāng)系統(tǒng)出現(xiàn)了多對(duì)多交互復(fù)雜的對(duì)象群時(shí),不要急于使用中介者模式,而要先反思你在系統(tǒng)上設(shè)計(jì)是否合理。
優(yōu)點(diǎn)就是集中控制,減少了對(duì)象之間的耦合度。缺點(diǎn)就是太過于集中。