вівторок, 29 серпня 2017 р.

Mediator

Медиатор – паттерн которые определяет внутри себя объект, в котором реализуется взаимодействие между некоторым количеством объектов. При этом эти объекты, могут даже не знать про существования друг друга, потому взаимодействий реализованых в медиаторе может быть огромное количество.

Когда использовать:

  1. Когда у вас есть некоторое количество объектов, и очень тяжело реализовать взаимодействие между ними. Яркий пример – умный дом. Есть неколько датчиков, и несколько устройств. К примеру, датчик температуры следит за тем какая на даный момент температура, а кондционер умеет охлаждать воздух. При чем кондиционер, не обязательно знает про существования датчика температуры. Есть центральный компьютер, который получает сигналы от каждого из устройств и понимает, что делать в том или ином случает
  2. Тяжело переиспользовать объект, так как он взаимодействует и коммуницирует с огромным количеством других объектов.
  3. Логика взаимодействия должна легко настраиваться и расширяться.

Собственно, пример медиатора даже писать безсмысленно, потому как это любой контроллер который мы используем во время нашей разработки. Посудите сами – на view есть очень много контролов, и все правила взаимодействия мы прописываем в контроллере. Элементарно.

И все же пример не будет лишним Давайте все же создадим пример который показывает создание аля умного дома.

Пускай у нас есть оборудование которое может взаимодействоать с нашим умным домом:

@class ASCentrallProcessor;

@interface ASSmartHousePart : NSObject

- (instancetype)initWithCore:(ASCentrallProcessor *)processor;

- (void)numbersChanged;

@end
@interface ASSmartHousePart ()

@property (nonatomic, strong) ASCentrallProcessor *processor;

@end

@implementation ASSmartHousePart

- (instancetype)initWithCore:(ASCentrallProcessor *)processor {
    self = [super init];
    
    if (self) {
        _processor = processor;
    }
    
    return self;
}

- (void)numbersChanged {
    [self.processor valueChanged:self];
}

@end

Теперь, создадим сердце нашего умного дома:

@class ASThermometer, ASConditioningSystem;
@class ASSmartHousePart;

@interface ASCentrallProcessor : NSObject

@property (nonatomic, strong) ASThermometer *thermometer;
@property (nonatomic, strong) ASConditioningSystem *condSystem;

- (void)valueChanged:(ASSmartHousePart *)part;

@end
@implementation ASCentrallProcessor

- (void)valueChanged:(ASSmartHousePart *)part {
    NSLog(@"Value changed! We need to do smth!");
    
    // detecting that changes are done by thermometer
    if ([part isKindOfClass:[ASThermometer class]]) {
        NSLog(@"Oh, the change is temperature");
        [self.condSystem startCondition];
    }
}

@end

Тут очень интересный момент – класс ASCentrallProcessor должен знать про существование ASSmartHousePart, собственно и ASSmartHousePart должен знать про существование ASCentrallProcessor. Если все сделать простым import – то проект не скомпилируется. Потому, в ASSmartHousePart.h мы добавили @class ASCentrallProcessor; для того чтобы Xcode знал что за объект будет использован, и при этом не импортил файл заголовков ASCentrallProcessor.

Заголовки же мы импортим в ASSmartHousePart.m.

Дальше в классе ASCentrallPart в методе valueChanged мы определяем с какой деталью и что произошло, чтобы адекватно среагировать. В нашем примере – изменение температуры приводит к тому что мы включаем кондиционер.

А вот, и код термометра и кондиционера:

@interface ASThermometer : ASSmartHousePart

@property (nonatomic, readonly) NSInteger temperature;

- (void)temperatureChanged:(NSInteger)temperature;

@end
@interface ASThermometer ()

@property (nonatomic) NSInteger temperature;

@end

@implementation ASThermometer

- (void)temperatureChanged:(NSInteger)temperature {
    self.temperature = temperature;
    [self numbersChanged];
}

@end
@interface ASConditioningSystem : ASSmartHousePart

- (void)startCondition;

@end
@implementation ASConditioningSystem

- (void)startCondition {
    NSLog(@"Conditioning...");
}

@end

Как видим в результате у нас есть два объекта, которые друг про друга не в курсе, и все таки они взаимодействуют друг с другом посредством нашего медиатора ASCentrallProcessor.

Код для тестинга:

    ASCentrallProcessor *proccessor = [[ASCentrallProcessor alloc] init];
    
    ASThermometer *therm = [[ASThermometer alloc] initWithCore:proccessor];
    ASConditioningSystem *condSystem = [[ASConditioningSystem alloc] initWithCore:proccessor];
    
    proccessor.condSystem = condSystem;
    proccessor.thermometer = therm;
    [therm temperatureChanged:45];

И конечно же лог:

2017-08-29 21:55:00.547 PatternsObjC[2786:97404] Value changed! We need to do smth!
2017-08-29 21:55:00.547 PatternsObjC[2786:97404] Oh, the change is temperature
2017-08-29 21:55:00.548 PatternsObjC[2786:97404] Conditioning...

Немає коментарів:

Дописати коментар

HyperComments for Blogger

comments powered by HyperComments