Zoeken…
Waarnemer patroon
Het waarnemerspatroon wordt gebruikt voor het afhandelen en delegeren van gebeurtenissen. Een onderwerp onderhoudt een verzameling waarnemers. Het onderwerp waarschuwt deze waarnemers vervolgens wanneer zich een gebeurtenis voordoet. Als je ooit addEventListener
hebt gebruikt, heb je het Observer-patroon gebruikt.
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
};
}
Voorbeeld gebruik:
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
Bemiddelaar patroon
Zie het bemiddelingspatroon als de vluchtcontroletoren die vliegtuigen in de lucht bestuurt: het stuurt dit vliegtuig nu aan land, het tweede om te wachten, en het derde om op te stijgen, enz. Geen vliegtuig mag echter ooit met zijn collega's praten .
Dit is hoe mediator werkt, het werkt als een communicatiehub tussen verschillende modules, op deze manier vermindert u de module-afhankelijkheid van elkaar, verhoogt u de losse koppeling en bijgevolg de draagbaarheid.
Dit Chatroom-voorbeeld legt uit hoe mediatorpatronen werken:
// 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();
}
Commando
Het opdrachtpatroon omvat parameters voor een methode, de huidige objectstatus en welke methode moet worden aangeroepen. Het is handig om alles wat nodig is om een methode op een later tijdstip aan te roepen te compartimenteren. Het kan worden gebruikt om een "commando" te geven en later te beslissen welk stuk code moet worden gebruikt om het commando uit te voeren.
Er zijn drie componenten in dit patroon:
- Commando bericht - het commando zelf, inclusief de methode naam, parameters en status
- Invoker - het gedeelte dat het commando opdraagt de instructies uit te voeren. Dit kan een getimede gebeurtenis, gebruikersinteractie, een stap in een proces, terugbellen of elke andere manier zijn die nodig is om de opdracht uit te voeren.
- Ontvanger - het doelwit van de uitvoering van de opdracht.
Commandobericht als een array
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
Constructor voor opdrachtklasse
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();
Kan beroep doen op:
- direct
- in reactie op een evenement
- in een volgorde van uitvoering
- als een terugbelreactie of als belofte
- aan het einde van een gebeurtenislus
- op elke andere manier die nodig is om een methode te gebruiken
Ontvanger
class Instructions {
DoThis( stringArg, numArg, objectArg, arrayArg ) {
console.log( `${stringArg}, ${numArg}, ${objectArg}, ${arrayArg}` );
}
}
Een client genereert een commando, geeft het door aan een invoker die het onmiddellijk uitvoert of het commando vertraagt, en dan werkt het commando op een ontvanger. Het opdrachtpatroon is erg handig in combinatie met begeleidende patronen om berichtpatronen te maken.
iterator
Een iteratorpatroon biedt een eenvoudige methode om achtereenvolgens het volgende item in een verzameling te selecteren.
Vaste verzameling
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 zijn iterators ingebouwd als een methode die klaar en waardevol is. klaar is waar wanneer de iterator aan het einde van de verzameling is
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"
}
}
Als een generator
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