Sök…
Observera mönster
Observer- mönstret används för händelsehantering och delegering. Ett ämne har en samling observatörer. Ämnet meddelar sedan dessa observatörer när en händelse inträffar. Om du någonsin har använt addEventListener
du använt Observer-mönstret.
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
};
}
Exempel på användning:
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
Medlarmönster
Tänk på medlarmönstret som flygkontrolltornet som styr flyg i luften: det leder detta plan att landa nu, det andra att vänta, och det tredje att ta av, etc. Inget flygplan får dock någonsin tala med sina kamrater .
Så fungerar medlaren, det fungerar som ett kommunikationsnav mellan olika moduler, på så sätt minskar du modulberoendet på varandra, ökar lös koppling och därmed bärbarhet.
Detta Chatroom-exempel förklarar hur medlarmönster fungerar:
// 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();
}
Kommando
Kommandomönstret kapslar parametrar till en metod, aktuellt objekttillstånd och vilken metod som ska ringas. Det är användbart att dela in allt som behövs för att kalla en metod vid ett senare tillfälle. Det kan användas för att utfärda ett "kommando" och senare bestämma vilket kodstycke som ska användas för att utföra kommandot.
Det finns tre komponenter i detta mönster:
- Kommandomeddelandet - själva kommandot, inklusive metodnamn, parametrar och tillstånd
- Invoker - den del som instruerar kommandot att utföra sina instruktioner. Det kan vara en tidsbestämd händelse, användarinteraktion, ett steg i en process, återuppringning eller något sätt som behövs för att köra kommandot.
- Mottagare - målet för kommandot exekvering.
Kommandomeddelandet som en matris
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
Konstruktör för kommandoklassen
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 åberopa:
- omedelbart
- som svar på en händelse
- i en sekvens av utförandet
- som ett återuppringningssvar eller i ett löfte
- i slutet av en händelsslinga
- på något annat sätt som krävs för att åberopa en metod
Mottagare
class Instructions {
DoThis( stringArg, numArg, objectArg, arrayArg ) {
console.log( `${stringArg}, ${numArg}, ${objectArg}, ${arrayArg}` );
}
}
En klient genererar ett kommando, skickar det till en invokare som antingen kör det omedelbart eller fördröjer kommandot, och sedan fungerar kommandot på en mottagare. Kommandomönstret är mycket användbart när det används med följeslagarmönster för att skapa meddelandemönster.
iterator
Ett iteratormönster tillhandahåller en enkel metod för att i tur och ordning välja nästa objekt i en samling.
Fast samling
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
I ECMAScript 2015 är iteratorer en inbyggd som en metod som returnerar gjort och värde. gjort är sant när iteratorn är i slutet av samlingen
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"
}
}
Som 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
I 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