Tuesday, February 24, 2009
Sunday, February 22, 2009
Intent: Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
//Define name space
var Visitor = {};
//The composite of elements
Visitor.ObjectStructure = function(){
var _elements = [];
this.attach = function(element){
_elements.push(element);
};
this.detach = function(element){
for(var i = 0; i < _elements.length; i++){
if(_elements[i] == element) _elements.splice(i, 1);
}
};
this.accept = function(visitor){
_elements.forEach(function(element){
element.accept(visitor);
});
};
};
//The concrete element will follow the same interface
Visitor.ElementA = function(){
this.accept = function(visitor){
visitor.visitElementA(this);
};
//Default operation of 'ElementA'
this.operationA = function(){
console.log('default operation of element A');
};
};
Visitor.ElementB = function(){
this.accept = function(visitor){
visitor.visitElementB(this);
};
//Default operation of 'ElementA'
this.operationB = function(){
console.log('default operation of element B');
};
};
//Visitor will follow the same interface
Visitor.VisistorA = function(){
this.visitElementA = function(elementA){
console.log("elementA is visited by visitorA");
};
this.visitElementB = function(elementA){
console.log("elementB is visited by visitorB");
};
};
Sunday, February 15, 2009
State Pattern with code
Definition: Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
var Machin = function(){
this.gearState = new Gear_0(0, this);
//Method
this.setGearState = function(state){
this.gearState = state;
};
this.getGearState = function(){
return this.gearState.getGearState();
};
this.setSpeed = function(speed){
this.gearState.setSpeed(speed);
};
this.getSpeed = function(){
return this.gearState.getSpeed();
};
}
/**
* Since javascript features it OOP with its duck typing
* thus we assume that all 'gears' class follow an interface 'gears'
*/
var Gear_0 = function(speed, machin){
this.speed = speed;
this.machin = machin;
this.setSpeed = function(speed){
this.speed = speed;
if(speed > 1) {
this.machin.setGearState(new Gear_1(this));
}
};
this.getSpeed = function(){
return this.speed;
};
this.getMachin = function(){
return this.machin;
};
this.getGearState = function(){
return 'Gear 0';
};
}
var Gear_1 = function(state){
this.speed = state.getSpeed();
this.machin = state.getMachin();
this.setSpeed = function(speed){
this.speed = speed;
if(this.speed > 30) this.machin.setGearState(new Gear_2(this));
else if(this.speed <> 0) this.machin.setGearState(new Gear_0(this.getSpeed()), this.getMachin());
};
this.getSpeed = function(){
return this.speed;
};
this.getMachin = function(){
return this.machin;
};
this.getGearState = function(){
return 'Gear 1';
};
};
var Gear_2 = function(state){
this.speed = state.getSpeed();
this.machin = state.getMachin();
this.setSpeed = function(speed){
this.speed = speed;
if(this.speed > 60) this.machin.setGearState(new Gear_3(this));
else if(this.speed <> 30) this.machin.setGearState(new Gear_2(this));
};
this.getSpeed = function(){
return this.speed;
};
this.getMachin = function(){
return this.machin;
};
this.getGearState = function(){
return 'Gear 2';
};
};
var Gear_3 = function(state){
this.speed = state.getSpeed();
this.machin = state.getMachin();
this.setSpeed = function(speed){
this.speed = speed;
if(this.speed > 80 ) this.machin.setGearState(new Gear_4(this));
else if(this.speed > 60 && this.speed < getspeed =" function(){" getmachin =" function(){" getgearstate =" function(){" gear_4 =" function(state){" speed =" state.getSpeed();" machin =" state.getMachin();" setspeed =" function(speed){" speed =" speed;"> 60 && this.speed <>
};
this.getSpeed = function(){
return this.speed;
};
this.getMachin = function(){
return this.machin;
};
this.getGearState = function(){
return 'Gear 4';
};
}
//1. speed at 0
var machin = new Machin();
machin.setSpeed(3);
//2. speed up
console.log(machin.getGearState());
machin.setSpeed(32);
console.log(machin.getGearState());
machin.setSpeed(62);
console.log(machin.getGearState());
machin.setSpeed(82);
console.log(machin.getGearState());
//3. slow down
machin.setSpeed(62);
console.log(machin.getGearState());
machin.setSpeed(32);
console.log(machin.getGearState());
Tuesday, February 10, 2009
shallow vs deep copy
Shallow copies: duplicate as little as possible. A shallow copy of a collection is a copy of the collection structure, not the elements. With a shallow copy, two collections now share the individual elements. constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
var obj1 = {foo: 'foo', bar: 'bar'};
var obj2 = obj1;
any changed in obj1 will also alter the content in obj2
Deep copies: duplicate everything. A deep copy of a collection is two collections with all of the elements in the original collection duplicated. constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original. deep copy is implemented as a 'prototype pattern'.
this.foo;
this.setFoo = function(value){
this.foo = value;
};
this.getFoo = function(){
return this.foo;
};
//clone method a deep copy
this.customClone = function(){
var tmp = new obj();
tmp.setFoo(this.getFoo());
return tmp;
};
};
var obj1 = new obj();
obj1.setFoo('foo');
var obj2 = obj1.customClone();
any changed in obj1 won't alter the content of obj2.
Wednesday, February 4, 2009
Test Double
Refer to Meszaros, the term Test Double as the generic term for any kind of pretend object used in place of a real object for testing purposes. The name comes from the notion of a Stunt Double in movies. (One of his aims was to avoid using any name that was already widely used.) Meszaros then defined four particular kinds of double:
- Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
- Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).
- Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.
- Mocks are what we are talking about here: objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
Javascript 'with' statement
see d'code
var obj = {foo: 'foo', bar: 'bar'};
with(obj){
foo = 'new foo';
bar = 'new bar';
}
or
var obj = {foo: 'foo', bar: 'bar'};
with(
obj,
{
foo: "new foo",
bar: "new bar"
}
);