中介者模式:使用中介者模式来集中相关对象之间复杂的沟通和控制方式。
中介者模式是行为型模式之一。
这里中介者模式的定义已经描述得很清楚了,不同的对象,之间因为沟通和控制会导致复杂的交互逻辑,这样,对象过多,那么逻辑会一团乱麻。
而使用中介者模式会将这些逻辑集中在中介者中处理。
使用中介者模式之后
- 每个对象在状态发生改变时都会通知中介者。
- 每个对象都会对中介者的请求做出响应。
下面我们还是举个简单的栗子吧
设想一下,我们有一个计时器,每隔2秒会调起咖啡机加热咖啡(假设咖啡2秒后冷却)。
定时器每隔3秒调用热水器加热饮用水(假设热水3秒后冷却)。
咖啡开始煮的时候暂停计时,煮热后再开启计时器(每次加热减少2个量的水,咖啡水量为某个设定的值,最大水量为20)。
热水器开始加热时暂停计时,沸腾后再开启计时器(热水器每次加热减少1个量的水,水量为某个设定的值)。
咖啡每次加热都会导致浓度增加,因此当达到一定当浓度的时候会需要热水器注入一定的热水。
这是咖啡机和热水器的协议(Java为接口)
#import <Foundation/Foundation.h>
@class Mediator;
NS_ASSUME_NONNULL_BEGIN
@protocol MechineProtocol <NSObject>
-(void)startWithMediator:(Mediator *)mediator;
-(void)stopWithMediator:(Mediator *)mediator;
@end
NS_ASSUME_NONNULL_END
咖啡机的实现
#import "CoffieMechine.h"
#import "Mediator.h"
@interface CoffieMechine ()
@property (nonatomic ,strong)NSTimer * timer;
@end
static NSInteger const MINSIZEOFCUPS = 12;
@implementation CoffieMechine
-(void)startWithMediator:(Mediator *)mediator {
NSLog(@"开始加热coffee...");
[mediator timerStopWithTarget:self];
//这里用一个定时器来模拟加热过程
_timer = [NSTimer scheduledTimerWithTimeInterval:5 repeats:NO block:^(NSTimer * _Nonnull timer) {
NSLog(@"加热coffee完成...");
self.cupsOfWater -= 2;
[mediator timerRestartWithTarget:self];
//水量警告位
if (self.cupsOfWater <= MINSIZEOFCUPS) {
[mediator addWaterWithTarget:self];
}
}];
}
-(void)stopWithMediator:(Mediator *)mediator {
[_timer invalidate];
_timer = nil;
}
@end
热水器的实现
#import "WaterMechine.h"
#import "Mediator.h"
@interface WaterMechine()
@property (nonatomic ,strong)NSTimer * timer;
@end
static NSInteger const MINSIZEOFCUPS = 8;
@implementation WaterMechine
- (void)startWithMediator:(Mediator *)mediator {
NSLog(@"开始加热water...");
[mediator timerStopWithTarget:self];
//这里用一个定时器来模拟加热过程
_timer = [NSTimer scheduledTimerWithTimeInterval:5 repeats:NO block:^(NSTimer * _Nonnull timer) {
NSLog(@"加热water完成...");
[self removeWaterWithMediator:mediator cups:1];
[mediator timerRestartWithTarget:self];
}];
}
-(void)stopWithMediator:(Mediator *)mediator {
[_timer invalidate];
_timer = nil;
}
-(void)addWaterWithMediator:(Mediator *)mediator cups:(NSInteger)cups {
self.cups += cups;
}
-(void)removeWaterWithMediator:(Mediator *)mediator cups:(NSInteger)cups {
self.cups -= cups;
[self checkWaterWithMediator:mediator];
}
-(void)checkWaterWithMediator:(Mediator *)mediator {
if (self.cups < MINSIZEOFCUPS) {
[mediator addWaterWithTarget:self];
}
}
@end
计时器的相关逻辑
#import "TimerMechine.h"
#import "Mediator.h"
@interface TimerMechine()
@property (nonatomic ,strong)NSMutableArray * targetArray;
@property (nonatomic ,strong)NSMutableArray * timerArray;
@property (nonatomic ,weak)Mediator * mediator;
@end
@implementation TimerMechine
-(NSMutableArray *)targetArray {
if(!_targetArray) {
_targetArray = [NSMutableArray array];
}return _targetArray;
}
-(NSMutableArray *)timerArray {
if (!_timerArray) {
_timerArray = [NSMutableArray array];
}return _timerArray;
}
-(void)createTimerWithMediator:(Mediator *)mediator interval:(NSTimeInterval)interval target:(id)target repeats:(BOOL)repeats{
self.mediator = mediator;
if (![self.targetArray containsObject:target]) {
__weak __typeof__(self) weakSelf = self;
NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:interval repeats:repeats block:^(NSTimer * _Nonnull timer) {
[weakSelf.mediator timerRunWithTarget:target];
}];
[self.timerArray addObject:@{@(interval):timer}];
[self.targetArray addObject:target];
}
}
-(void)stopTimerWithTarget:(id)target {
NSInteger index = [self.targetArray indexOfObject:target];
NSTimer * timer = [[self.timerArray objectAtIndex:index] allValues][0];
if (timer.fireDate != [NSDate distantFuture]) {
[timer setFireDate:[NSDate distantFuture]];
}
}
-(void)startTimerWithTarget:(id)target {
if ([self.targetArray containsObject:target]) {
NSInteger index = [self.targetArray indexOfObject:target];
NSTimer * timer = [[self.timerArray objectAtIndex:index] allValues][0];
NSTimeInterval interval = [[[self.timerArray objectAtIndex:index] allKeys][0] doubleValue];
if (timer.fireDate != [NSDate distantPast]) {
[timer setFireDate:[NSDate dateWithTimeIntervalSinceNow:interval]];
}
}
}
//在水位过低时应该允许关闭计时器保护机器
-(void)removeAllTarget {
[self.targetArray removeAllObjects];
[self.timerArray enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull temp, NSUInteger idx, BOOL * _Nonnull stop) {
NSTimer * timer = [temp allValues][0];
[timer invalidate];
timer = nil;
}];
[self.timerArray removeAllObjects];
}
@end
中介者逻辑
#import "Mediator.h"
@interface Mediator ()
@property (nonatomic ,strong)TimerMechine * timeMechine;
@property (nonatomic ,strong)CoffieMechine * coffieMechie;
@property (nonatomic ,strong)WaterMechine * waterMechine;
@end
@implementation Mediator
-(instancetype)initWithTimeMechine:(TimerMechine *)timeMechine coffieMechine:(CoffieMechine *)coffieMechie waterMechine:(WaterMechine *)waterMechine {
if (self = [super init]) {
_timeMechine = timeMechine;
_coffieMechie = coffieMechie;
_waterMechine = waterMechine;
}return self;
}
//调用暂停计时器
-(void)timerStopWithTarget:(nullable id)target {
[_timeMechine stopTimerWithTarget:target];
}
//重新开始计时器
-(void)timerRestartWithTarget:(id)target {
[_timeMechine startTimerWithTarget:target];
}
//计时器触发事件
-(void)timerRunWithTarget:(nullable id)target {
id<MechineProtocol> mTarget = target;
[mTarget startWithMediator:self];
}
//水位不足时加水
-(void)addWaterWithTarget:(id)target {
if (target == _waterMechine) {
NSLog(@"NO water");
}else if (target == _coffieMechie) {
NSInteger cups = _waterMechine.cups;
if (cups > 5) {
[_waterMechine removeWaterWithMediator:self cups:5];
_coffieMechie.cupsOfWater += 5;
return;
}else {
//停止烧水
[_waterMechine stopWithMediator:self];
[_waterMechine removeWaterWithMediator:self cups:cups];
_coffieMechie.cupsOfWater += cups;
}
if (_coffieMechie.cupsOfWater <= 8) {
[self stopAll];
}
}
}
//水位严重不足时停止所有机器
-(void)stopAll {
[_timeMechine removeAllTarget];
[_waterMechine stopWithMediator:self];
[_coffieMechie stopWithMediator:self];
NSLog(@"全部停止");
}
@end
正常调用
_timeMechine = [[TimerMechine alloc] init];
_coffieMechine = [[CoffieMechine alloc] init];
_coffieMechine.cupsOfWater = 12;
_waterMechine = [[WaterMechine alloc] init];
_waterMechine.cups = 2;
_mediator = [[Mediator alloc] initWithTimeMechine:_timeMechine coffieMechine:_coffieMechine waterMechine:_waterMechine];
[_timeMechine createTimerWithMediator:_mediator interval:3 target:_coffieMechine repeats:YES];
[_timeMechine createTimerWithMediator:_mediator interval:3 target:_waterMechine repeats:YES];
优点
1.通过对象彼此解耦,可以提高对象的复用性
2.通过控制逻辑集中,简化系统维护
3.简化对象之间消息的发送。减少消息的数量
缺点
如果设计不当,中介者本身可能会变得过于复杂
中介者往往被用来协调GUI组件。
网友评论