Шаблоны программирования на Swift: Mediator

Mediator_example-2x_proSwift_ru

Давайте разберем шаблон программирования Mediator  на Swift

Mediator

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

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

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

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

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

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

//
// proSwift.ru
//

class SmartHousePart {
    private weak var processor: CentralProcessor
    
    init(withCore processor: CentralProcessor) {
        self .processor = processor
    }
    
    func numberChanged() {
        processor.valueChanged(self)
    }
}

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

//
// proSwift.ru
//

class CentralProcessor {
    var thermometer:  Thermometer?
    var condSystem: ConditioningSystem?
    
    func valueChanged(aPart: SmartHousePart) {
        print("значение изменилось! нужно что-то сделать")
        
        // Определяем, что изменилась именно темперетура
        if aPart is Thermometer {
            print("Да - изменилась именно температура, включим кондер...")
            condSystem?.startCondition()
        }
        
    }
}

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

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

//
// proSwift.ru
//

class Thermometer: SmartHousePart {
    var temperature: Int?
    
    func temperatureChanged(temperature: Int) {
        self.temperature = temperature
        self.numberChanged()
    }
}

class ConditioningSystem: SmartHousePart {
    func startCondition() {
        print("Охлаждаю")
    }
}

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

//
// proSwift.ru
//

let processor = CentralProcessor()

let therm = Thermometer(withCore: processor)
let cond = ConditioningSystem(withCore: processor)

processor.condSystem = cond
processor.thermometer = therm

therm.temperatureChanged(45)

Вывод лога в консоль:

значение изменилось! нужно что-то сделать
Да - изменилась именно температура, включим кондер...
Охлаждаю

Пример с GitHub

Шаблон Mediator используется для уменьшения связи между классами, которые взаимодействуют друг с другом. Вместо того, чтобы классы общались непосредственно друг с другом, и, таким образом, требуя знания о реализации друг-друга, классы отправляют сообщения   объекту — посреднику и взаимодействуют с помощью этого посредника.

//
// proSwift.ru
//
// https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/source/structural/facade.swift 


class Colleague {
    let name: String
    let mediator: Mediator
    
    init(name: String, mediator: Mediator) {
        self.name = name
        self.mediator = mediator
    }
    
    func send(message: String) {
        mediator.send(message, colleague: self)
    }
    
    func receive(message: String) {
        assert(false, "Method should be overriden")
    }
}

protocol Mediator {
    func send(message: String, colleague: Colleague)
}

class MessageMediator: Mediator {
    private var colleagues: [Colleague] = []
    
    func addColleague(colleague: Colleague) {
        colleagues.append(colleague)
    }
    
    func send(message: String, colleague: Colleague) {
        for c in colleagues {
            if c !== colleague { //for simplicity we compare object references
                c.receive(message)
            }
        }
    }
}

class ConcreteColleague: Colleague {
    override func receive(message: String) {
        print("Colleague \(name) received: \(message)")
    }
}

// ### Usage:

let messagesMediator = MessageMediator()
let user0 = ConcreteColleague(name: "0", mediator: messagesMediator)
let user1 = ConcreteColleague(name: "1", mediator: messagesMediator)
messagesMediator.addColleague(user0)
messagesMediator.addColleague(user1)

user0.send("Hello") // user1 receives message

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

Метки:
2 комментария на “Шаблоны программирования на Swift: Mediator
  1. Максим:

    не нужно ли сделать слабую ссылку на процессор? будет утечка памяти
    class SmartHousePart {
    private weak var processor: CentralProcessor

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

*

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.