NazimovDmitrii
8/27/2019 - 9:13 PM

[JS ES6 Паттерн ПОСРЕДНИК (mediator) ] #js #ES6 #ООП #Паттерны

[JS ES6 Паттерн ПОСРЕДНИК (mediator) ] #js #ES6 #ООП #Паттерны

/**
 *
 * ПАТТЕРН ПОСРЕДНИК (mediator)
 *
 * Паттерн ПОСРЕДНИК (mediator) -  это поведенческий паттерн проектирования, который позволяет уменьшить связанность
 * множества классов между собой, благодаря перемещению этих связей в один класс-посредник.
 * Паттерн Посредник используется для централизации сложных взаимодействий и управляющих операций между объектами.
 * Один из модулей медиатора изменяет состояние -> оповещает об этом медиатор -> медиатор оповещает об этом другие
 * модули, которым положено знать о случившемся.
 * Довольно популярна реализация Посредника при помощи Наблюдателя. При этом объект посредника будет выступать 
 * издателем, а все остальные компоненты станут подписчиками и смогут динамически следить за событиями, происходящими 
 * в посреднике. В этом случае трудно понять, чем же отличаются оба паттерна.
 * Но Посредник имеет и другие реализации, когда отдельные компоненты жёстко привязаны к объекту посредника. 
 * Такой код вряд ли будет напоминать Наблюдателя, но всё же останется Посредником.
 * Напротив, в случае реализации посредника с помощью Наблюдателя представим такую программу, в которой каждый компонент 
 * системы становится издателем. Компоненты могут подписываться друг на друга, в то же время не привязываясь к 
 * конкретным классам. Программа будет состоять из целой сети Наблюдателей, не имея центрального объекта-Посредника.
 *
 */


// Mediator
class ChatRoom {
    showMessage(user, message) {
        const time = new Date()
        const sender = user.getName()

        console.log(time + '[' + sender + ']:' + message)
    }
}

class User {
    constructor(name, chatMediator) {
        this.name = name
        this.chatMediator = chatMediator
    }

    getName() {
        return this.name
    }

    send(message) {
        this.chatMediator.showMessage(this, message)
    }
}

const mediator = new ChatRoom()

const john = new User('John Doe', mediator)
const jane = new User('Jane Doe', mediator)

john.send('Hi there!')
jane.send('Hey!')

// Output will be
// Feb 14, 10:58 [John]: Hi there!
// Feb 14, 10:58 [Jane]: Hey!






//Более сложный вариант, тут соблюдены все формальности данного паттерна, но он получился чересчур абстрактным и громоздким
class Mediator {
    constructor() {
    }

    ColleagueChanged(colleague) {

    }
}

class ConcreteMediator extends Mediator {
    constructor() {
        super()
        console.log('ConcreteMediator created')
        this.colleague1 = new ConcreteColleague1(this)
        this.colleague2 = new ConcreteColleague2(this)
    }

    ColleagueChanged(colleague) {
        switch(colleague) {
            case this.colleague1:
                console.log('ConcreteColleague1 has Changed -> change ConcreteColleague2.feature: ')
                this.colleague2.setFeature('new feature 2');
                break;
            case this.colleague2:
                console.log('ConcreteColleague2 has Changed, but do nothing')
                break
            default:
                console.log('Do nothing')
        }
    }
}

class Colleague {
    constructor() {
    }

    Changed() {
        this.mediator.ColleagueChanged(this)
    }
}

class ConcreteColleague1 extends Colleague {
    constructor(mediator) {
        super()
        console.log('ConcreteColleague1 created')
        this.mediator = mediator
        this.feature = "feature 1"
    }

    setFeature(feature) {
        console.log('ConcreteColleague1 Feature has changed from ' + this.feature + ' to ' + feature)
        this.feature = feature
        this.Changed()
    }
}
class ConcreteColleague2 extends Colleague {
    constructor(mediator) {
        super()
        console.log('ConcreteColleague2 created')
        this.mediator = mediator
        this.feature = "feature 2"
    }

    setFeature(feature) {
        console.log('ConcreteColleague2 Feature has changed from ' + this.feature + ' to ' + feature)
        this.feature = feature
        this.Changed()
    }
}


function init_Mediator() {
    var mediator = new ConcreteMediator();
    mediator.colleague1.setFeature("new feature 1");