Ricerca…
Modello di osservatore
Il pattern Observer viene utilizzato per la gestione degli eventi e la delega. Un soggetto mantiene una collezione di osservatori. Il soggetto quindi notifica questi osservatori ogni volta che si verifica un evento. Se hai mai usato addEventListener
, hai utilizzato il pattern Observer.
function Subject() {
this.observers = []; // Observers listening to the subject
this.registerObserver = function(observer) {
// Add an observer if it isn't already being tracked
if (this.observers.indexOf(observer) === -1) {
this.observers.push(observer);
}
};
this.unregisterObserver = function(observer) {
// Removes a previously registered observer
var index = this.observers.indexOf(observer);
if (index > -1) {
this.observers.splice(index, 1);
}
};
this.notifyObservers = function(message) {
// Send a message to all observers
this.observers.forEach(function(observer) {
observer.notify(message);
});
};
}
function Observer() {
this.notify = function(message) {
// Every observer must implement this function
};
}
Esempio di utilizzo:
function Employee(name) {
this.name = name;
// Implement `notify` so the subject can pass us messages
this.notify = function(meetingTime) {
console.log(this.name + ': There is a meeting at ' + meetingTime);
};
}
var bob = new Employee('Bob');
var jane = new Employee('Jane');
var meetingAlerts = new Subject();
meetingAlerts.registerObserver(bob);
meetingAlerts.registerObserver(jane);
meetingAlerts.notifyObservers('4pm');
// Output:
// Bob: There is a meeting at 4pm
// Jane: There is a meeting at 4pm
Modello del mediatore
Pensa al modello di mediatore come la torre di controllo del volo che controlla gli aerei in aria: dirige questo aereo per atterrare ora, il secondo per aspettare, e il terzo per decollare, ecc. Tuttavia nessun aereo è mai permesso di parlare con i suoi pari .
Questo è il modo in cui funziona il mediatore, funziona come un hub di comunicazione tra diversi moduli, in questo modo si riduce la dipendenza tra moduli, aumenta l'accoppiamento libero e di conseguenza la portabilità.
Questo esempio di Chatroom spiega come funzionano i modelli di mediatore:
// each participant is just a module that wants to talk to other modules(other participants)
var Participant = function(name) {
this.name = name;
this.chatroom = null;
};
// each participant has method for talking, and also listening to other participants
Participant.prototype = {
send: function(message, to) {
this.chatroom.send(message, this, to);
},
receive: function(message, from) {
log.add(from.name + " to " + this.name + ": " + message);
}
};
// chatroom is the Mediator: it is the hub where participants send messages to, and receive messages from
var Chatroom = function() {
var participants = {};
return {
register: function(participant) {
participants[participant.name] = participant;
participant.chatroom = this;
},
send: function(message, from) {
for (key in participants) {
if (participants[key] !== from) {//you cant message yourself !
participants[key].receive(message, from);
}
}
}
};
};
// log helper
var log = (function() {
var log = "";
return {
add: function(msg) { log += msg + "\n"; },
show: function() { alert(log); log = ""; }
}
})();
function run() {
var yoko = new Participant("Yoko");
var john = new Participant("John");
var paul = new Participant("Paul");
var ringo = new Participant("Ringo");
var chatroom = new Chatroom();
chatroom.register(yoko);
chatroom.register(john);
chatroom.register(paul);
chatroom.register(ringo);
yoko.send("All you need is love.");
yoko.send("I love you John.");
paul.send("Ha, I heard that!");
log.show();
}
Comando
Il modello di comando incapsula i parametri in un metodo, lo stato corrente dell'oggetto e quale metodo chiamare. È utile compartimentare tutto ciò che è necessario per chiamare un metodo in un secondo momento. Può essere utilizzato per emettere un "comando" e decidere in seguito quale parte di codice utilizzare per eseguire il comando.
Ci sono tre componenti in questo modello:
- Comando Messaggio: il comando stesso, incluso il nome del metodo, i parametri e lo stato
- Invoker: la parte che indica al comando di eseguire le sue istruzioni. Può essere un evento a tempo, l'interazione dell'utente, un passaggio in un processo, una richiamata o qualsiasi modo necessario per eseguire il comando.
- Ricevitore - l'obiettivo dell'esecuzione del comando.
Messaggio di comando come matrice
var aCommand = new Array();
aCommand.push(new Instructions().DoThis); //Method to execute
aCommand.push("String Argument"); //string argument
aCommand.push(777); //integer argument
aCommand.push(new Object {} ); //object argument
aCommand.push(new Array() ); //array argument
Costruttore per la classe di comando
class DoThis {
constructor( stringArg, numArg, objectArg, arrayArg ) {
this._stringArg = stringArg;
this._numArg = numArg;
this._objectArg = objectArg;
this._arrayArg = arrayArg;
}
Execute() {
var receiver = new Instructions();
receiver.DoThis(this._stringArg, this._numArg, this._objectArg, this._arrayArg );
}
}
invoker
aCommand.Execute();
Può invocare:
- subito
- in risposta a un evento
- in una sequenza di esecuzione
- come una risposta callback o in una promessa
- alla fine di un ciclo di eventi
- in qualsiasi altro modo necessario per invocare un metodo
Ricevitore
class Instructions {
DoThis( stringArg, numArg, objectArg, arrayArg ) {
console.log( `${stringArg}, ${numArg}, ${objectArg}, ${arrayArg}` );
}
}
Un client genera un comando, lo passa a un invocatore che lo esegue immediatamente o ritarda il comando, quindi il comando agisce su un ricevitore. Il pattern di comando è molto utile se usato con pattern companion per creare pattern di messaggistica.
Iterator
Un pattern iteratore fornisce un metodo semplice per selezionare sequenzialmente l'elemento successivo in una raccolta.
Raccolta corretta
class BeverageForPizza {
constructor(preferenceRank) {
this.beverageList = beverageList;
this.pointer = 0;
}
next() {
return this.beverageList[this.pointer++];
}
var withPepperoni = new BeverageForPizza(["Cola", "Water", "Beer"]);
withPepperoni.next(); //Cola
withPepperoni.next(); //Water
withPepperoni.next(); //Beer
In ECMAScript 2015 gli iteratori sono un built-in come metodo che restituisce fatto e valore. fatto è vero quando l'iteratore è alla fine della raccolta
function preferredBeverage(beverage){
if( beverage == "Beer" ){
return true;
} else {
return false;
}
}
var withPepperoni = new BeverageForPizza(["Cola", "Water", "Beer", "Orange Juice"]);
for( var bevToOrder of withPepperoni ){
if( preferredBeverage( bevToOrder ) {
bevToOrder.done; //false, because "Beer" isn't the final collection item
return bevToOrder; //"Beer"
}
}
Come un generatore
class FibonacciIterator {
constructor() {
this.previous = 1;
this.beforePrevious = 1;
}
next() {
var current = this.previous + this.beforePrevious;
this.beforePrevious = this.previous;
this.previous = current;
return current;
}
}
var fib = new FibonacciIterator();
fib.next(); //2
fib.next(); //3
fib.next(); //5
In ECMAScript 2015
function* FibonacciGenerator() { //asterisk informs javascript of generator
var previous = 1;
var beforePrevious = 1;
while(true) {
var current = previous + beforePrevious;
beforePrevious = previous;
previous = current;
yield current; //This is like return but
//keeps the current state of the function
// i.e it remembers its place between calls
}
}
var fib = FibonacciGenerator();
fib.next().value; //2
fib.next().value; //3
fib.next().value; //5
fib.next().done; //false