Beruflich Dokumente
Kultur Dokumente
Presentation by:
ADMEC Multimedia Institute
Topics to Cover
console.log( civic.toString() );
console.log( mondeo.toString() );
The Module Pattern
// Usage:
// Increment our counter
testModule.incrementCounter();
// Check the counter value and reset
// Outputs: counter value prior to reset: 1
testModule.resetCounter();
The Module Pattern Example
Here, other parts of the code are unable to directly read the value
of our incrementCounter() or resetCounter(). The counter variable
is actually fully shielded from our global scope so it acts just like a
private variable would - its existence is limited to within the
module's closure so that the only code able to access its scope are
our two functions.
Our methods are effectively namespaced so in the test section of
our code, we need to prefix any calls with the name of the module
(e.g. "testModule").
The Singleton Pattern
function init() {
// Singleton
var privateRandomNumber = Math.random();
return {
getRandomNumber: function() {
return privateRandomNumber;
}
};
};
return {
// Always create a new Singleton instance
getInstance: function () {
instance = init();
return instance;
The Singleton Pattern Example
}
};
})();
// Usage:
// be valid.
Note:
What makes the Singleton is the global access to the instance (generally
through MySingleton.getInstance()) as we don't (at least in static
languages) call new MySingleton() directly.
The Observer Pattern
We can now expand on what we've learned to implement the Observer pattern with the following
components:
Observer: provides a update interface for objects that need to be notified of a Subject's changes of
state
First, let's model the list of dependent Observers a subject may have:
function ObserverList(){
this.observerList = [];
}
The Observer Pattern Example
i++;
}
return -1;
};
};
Next, let's model the Subject and the ability to add, remove or notify observers on
the observer list.
The Observer Pattern Example
function Subject(){
this.observers.add( observer );
};
};
this.observers.get(i).update( context );
};
We then define a skeleton for creating new Observers. The update functionality here will be overwritten later with
custom behaviour.
// The Observer
function Observer(){
this.update = function(){
// ...
};
In our sample application using the above Observer components, we now define:
The Observer Pattern Example
Sample script:
obj[key] = extension[key];
// Concrete Subject
controlCheckbox.onclick = function(){
controlCheckbox.notify( controlCheckbox.checked );
};
addBtn.onclick = addNewObserver;
The Observer Pattern Example
// Concrete Observer
function addNewObserver(){
check.type = "checkbox";
this.checked = value;
};
The Observer Pattern Example
controlCheckbox.addObserver( check );
A simple implementation of the Mediator pattern can be found below, exposing both publish() and
subscribe() methods for use:
//Storage for topics that can be broadcast or listened to var topics = {};
if ( !topics[topic] ){
return this;
};
The Mediator Pattern Example
var args;
if ( !topics[topic] ){
return false;
return this;
The Mediator Pattern Example
};
return {
Publish: publish,
Subscribe: subscribe,
obj.subscibe = subscribe;
obj.publish = publish;
};
}() );
The Prototype Pattern
drive: function () {
},
panic: function () {
};
console.log( yourCar.name );
Object.create also allows us to easily implement advanced concepts such as differential inheritance
where objects are able to directly inherit from other objects. We saw earlier that Object.create allows us to
initialise object properties using the second supplied argument. For example:
var vehicle = {
getModel: function () {
};
"id": {
value: MY_GLOBAL.nextId(),
The Prototype Pattern Example
enumerable: true
},
"model": {
value: "Ford",
enumerable: true
});
Here the properties can be initialized on the second argument of Object.create using an object literal with
a syntax similar to that used by the Object.defineProperties and Object.defineProperty methods that we
looked at previously.
It is worth noting that prototypal relationships can cause trouble when enumerating properties of objects
and (as Crockford recommends) wrapping the contents of the loop in a hasOwnProperty() check.
The Prototype Pattern Example
If we wish to implement the prototype pattern without directly using Object.create, we can simulate the
pattern as per the above example as follows:
var vehiclePrototype = {
this.model = carModel;
},
getModel: function () {
};
F.prototype = vehiclePrototype;
The Prototype Pattern Example
f.init( model );
return f;
car.getModel();
Note: This alternative does not allow the user to define read-only properties in the same manner (as the
vehiclePrototype may be altered if not careful).
function F() {}
F.prototype = proto;
The Prototype Pattern Example
};
})();
if( el.addEventListener ){
}else if(el.attachEvent){
} else{
};
Factory Pattern
The following is an example that builds upon our previous snippets using the Constructor pattern logic to
define cars. It demonstrates how a Vehicle Factory may be implemented using the Factory pattern:
// some defaults
this.doors = options.doors || 4;
// FactoryExample.js
function VehicleFactory() {}
VehicleFactory.prototype.vehicleClass = Car;
switch(options.vehicleType){
case "car":
this.vehicleClass = Car;
break;
case "truck":
this.vehicleClass = Truck;
break;
};
The Factory Pattern Example
vehicleType: "car",
color: "yellow",
doors: 6 } );
// Test to confirm our car was created using the vehicleClass/prototype Car
// Outputs: true
console.log( car );
The Factory Pattern Example
vehicleType: "truck",
color: "red",
wheelSize: "small" } );
// Test to confirm our truck was created with the vehicleClass/prototype Truck
// Outputs: true
console.log( movingTruck );
The Factory Pattern Example
Approach #2: Subclass VehicleFactory to create a factory class that builds Trucks
function TruckFactory () {}
TruckFactory.prototype.vehicleClass = Truck;
color: "pink",
// Outputs: true
// Outputs: Truck object with the color "pink", wheelSize "so big"
console.log( myBigTruck );
The Decorator pattern isn't heavily tied to how objects are created but instead focuses on
the problem of extending their functionality. Rather than just relying on prototypal
inheritance, we work with a single base object and progressively add decorator objects
which provide the additional capabilities. The idea is that rather than sub-classing, we
add (decorate) properties or methods to a base object so it's a little more streamlined.
// A vehicle constructor
this.model = "default";
this.license = "00000-000";
console.log( testInstance );
// Outputs:
this.model = modelName;
};
this.color = color;
};
truck.setModel( "CAT" );
truck.setColor( "blue" );
console.log( truck );
// Outputs:
console.log( secondInstance );
// Outputs:
This type of simplistic implementation is functional, but it doesn't really demonstrate all of
the strengths Decorators have to offer. For this, we're first going to go through my
variation of the Coffee example from an excellent book called Head First Design Patterns
by Freeman, Sierra and Bates, which is modeled around a Macbook purchase.
Example 2: Decorating Objects With Multiple Decorators
function MacBook() {
// Decorator 1
var v = macbook.cost();
macbook.cost = function() {
return v + 75;
};
}
// Decorator 2
var v = macbook.cost();
macbook.cost = function(){
return v + 200;
};
// Decorator 3
var v = macbook.cost();
macbook.cost = function(){
return v + 250;
};
memory( mb );
engraving( mb );
insurance( mb );
// Outputs: 1522
console.log( mb.cost() );
// Outputs: 11.6
console.log( mb.screenSize() );
In the above example, our Decorators are overriding the MacBook() super-class
objects .cost() function to return the current price of the Macbook plus the cost
of the upgrade being specified.
It's considered a decoration as the original Macbook objects constructor
methods which are not overridden (e.g. screenSize()) as well as any other
properties which we may define as a part of the Macbook remain unchanged
and intact.
There isn't really a defined interface in the above example and we're shifting
away the responsibility of ensuring an object meets an interface when moving
from the creator to the receiver.
JavaScript MV* Patterns
Special thanks to