#javascript #события #javascript_events
Есть следующая задача.
Даны класс Rabbit и класс Hunter. Rabbit может менять свои координаты x и y. Нужно
сделать так, чтобы при изменении координат охотники, созданные через конструктор вне
зависимости от их количества могли получать эти координаты, то есть были подписаны
на изменения в Rabbit. Код выглядит так:
'use strict';
class Rabbit {
constructor(name) {
this.name = name;
this.x = 0;
this.y = 0;
}
move() {
this.x = (Math.random() * 100).toFixed(0);
this.y = (Math.random() * 100).toFixed(0);
console.log(this.x, this.y, this.name + ' ' + 'moved');
}
}
class Hunter {
constructor(name) {
this.name = name;
}
}
let rabbit = new Rabbit("Jonny");
rabbit.move();
let hunter1 = new Hunter("Ted");
let hunter2 = new Hunter("Billy");
let hunter3 = new Hunter("Greg");
Полагаю, что классу Hunter нужен какой-нибудь метод notification, а классу Rabbit
передавался массив подписчиков, которым нужно передать данные, но как это реализовать,
не пойму.
Ответы
Ответ 1
class Rabbit { constructor(name) { this.name = name; this.x = 0; this.y = 0; this.handlersMove = []; } move() { this.x = (Math.random() * 100).toFixed(0); this.y = (Math.random() * 100).toFixed(0); console.log(this.x, this.y, this.name + ' ' + 'moved'); this.handlersMove.forEach(handler => handler(this)); } } class Hunter { constructor(name) { this.name = name; } onGameMoves(game) { console.log(`${this.name} sees that ${game.constructor.name} ${game.name} moved to (${game.x}, ${game.y}).`); } } let rabbit = new Rabbit("Jonny"); let hunter1 = new Hunter("Ted"); rabbit.handlersMove.push(hunter1.onGameMoves.bind(hunter1)); let hunter2 = new Hunter("Billy"); let hunter3 = new Hunter("Greg"); rabbit.handlersMove.push(hunter3.onGameMoves.bind(hunter3)); rabbit.move();Ответ 2
Вы в своём вопросе на него же и ответили, воспользуйтесь шаблоном публикатор-подписчик. Все это выглядит примерно так: Где то в начале создаётся глобальный объект, назовём его broker который имеет 2 метода fire(отправить событие) и on(подписаться на событие) let broker = new Broker(); Затем все Hunter при создании подписываются на событие rabbit-moved broker.on("rabbit-moved", hunt) Тут я предположил что у охотника есть метод hunt(eventContext) в котором находится код логики охоты Когда произойдёт изменение координат какого либо Rabbit, то есть внутри вашего метода Rabbit.move() вы отправляете событие rabbit-moved broker.fire("rabbit-moved", eventContext) Вторым аргументом тут идёт объект, который будет содержать всю необходимую информацию об обработке этого события, в нашем случае это x и y наших кроликов. Брокер отправляет это сообщение всем подписчикам, topic - на картинке выше, это имя нашего события Сам брокер может отличаться тяжестью случая, самая простая версия выглядит примерно так class Broker { constructor() { // массивы подписчиков привязанные к каждому топику this.subscribers = {}; } // метод подписки on(topic, func) { if (!this.subscribers[topic]) this.subscribers[topic] = []; this.subscribers[topic].push(func); } // метод оповещения подписчиков fire(topic, data) { if (this.subscribers[topic]) this.subscribers[topic].forEach(l => l(data)); } } // создаётся глобальный объект, который связывает публикаторов и подписчиков let broker = new Broker(); class Rabbit { constructor(name) { this.name = name; this.x = 0; this.y = 0; this.handlersMove = []; } move() { this.x = (Math.random() * 100).toFixed(0); this.y = (Math.random() * 100).toFixed(0); // все кролики в момент перемещение публикуют событие broker.fire('rabbit-moved', this); } } class Hunter { constructor(name) { this.name = name; // все охотники подписаны на топик "rabbit-moved" // и когда приходит данное событие вызывается метод hunt broker.on('rabbit-moved', data => this.hunt(data)) } hunt(data) { console.log(`Hunter ${this.name}: I saw ${data.name} at ${data.x}:${data.y}`); } } // создаем 10 кроликов и 2 охотника let rabbits = Array(10).fill(0).map((e, i) => new Rabbit(`Rabbit ${i+1}`)); new Hunter("Tom") new Hunter("Max") function moveRandomRabbit() { // перемещение случайного кролика в случайную точку rabbits[Math.floor(Math.random() * rabbits.length)].move(); }
Комментариев нет:
Отправить комментарий