問題:
在軟件的開發(fā)過程中怜跑,勢必會碰到這樣一種情況样勃,多個類或多個子系統(tǒng)相互交互吠勘,而且交互很繁瑣,導致每個類都必須知道他需要交互的類峡眶,這樣它們的耦合會顯得異常厲害剧防。牽一發(fā)而動全身,
好了辫樱,既然問題提出來了峭拘,那有請我們這期的主角——中介者模式出場吧!
中介者模式
用一個中介者對象來封裝一系列的對象交互狮暑。中介者使得各對象不需要顯式地相互引用鸡挠,從而使其松散耦合,而且可以獨立地改變它們之間的交互搬男。
中介者模式結(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:@"下一個" 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:@"下一個" 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 = @"我是藍色控制器";
[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:@"下一個" 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() {};
};
// 具體的同事類:班長
class Monitor : public Colleage{
public:
Monitor(string n = ""): Colleage(n){};
virtual void talk(){
cout<<"大班長說:"<<getContent()<<endl;
}
};
//具體的同事類:團支書
class TuanZhiShu: public Colleage{
public:
TuanZhiShu(string n = " "): Colleage(n){};
virtual void talk (){
cout<<"團支書說:"<<getContent()<<endl;
}
};
//具體的同事類:同學A
class StudentA: public Colleage{
public:
StudentA(string n = ""):Colleage(n){};
virtual void talk(){
cout<<"學生A說:"<<getContent()<<endl;
}
};
//具體的同事類:同學B
class StudentB : public Colleage{
public:
StudentB(string n = ""): Colleage(n){};
virtual void talk(){
cout << "同學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通訊平臺
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<<"下面的班長發(fā)布一個通知的場景:"<<endl;
//將同學們加入到qq群中
qq.addStudent(&studentMonitor);
qq.addStudent(&studentTuanZhiShu);
qq.addStudent(&studentA);
qq.addStudent(&studentB);
//設(shè)置大家的回復消息
studentMonitor.setContent("明天下午2點開年紀會拣展,收到回復");
studentTuanZhiShu.setContent("知道了,肯定到");
studentA.setContent("收到了缔逛,但是可能晚點到");
studentB.setContent("收到了备埃,但是明天考試");
//開始發(fā)通知
qq.notify(&studentMonitor);
cout<<endl<<"下面是兩個同學的私下交流"<<endl;
studentMonitor.setContent("你覺得我們的老師怎么樣");
studentA.setContent("我覺得不好");
qq.chart(&studentMonitor, &studentA);
}
下面的班長發(fā)布一個通知的場景:
大班長說:明天下午2點開年紀會,收到回復
團支書說:知道了褐奴,肯定到
學生A說:收到了按脚,但是可能晚點到
同學B說:收到了,但是明天考試
下面是兩個同學的私下交流
大班長說:你覺得我們的老師怎么樣
學生A說:我覺得不好
總結(jié):
中介者模式很容易在系統(tǒng)中應(yīng)用敦冬,也很容易在系統(tǒng)中誤用辅搬。當系統(tǒng)出現(xiàn)了多對多交互復雜的對象群時,不要急于使用中介者模式匪补,而要先反思你在系統(tǒng)上設(shè)計是否合理伞辛。
優(yōu)點就是集中控制,減少了對象之間的耦合度夯缺。缺點就是太過于集中蚤氏。