new Factory()

A factory for classes allowing them to be registered and created using a friendly name.

Description

This class allows other classes to register themselves for use at a later time. Depending on how you intend to use the registered classes you can also specify a load and execution order through the priority parameter of the register method.

Members


<readonly> registered :Object.<string, Object>

An object containing all registered classes.

Examples

The following shows the structure of this object. The <name> placeholders would be the name the class was registered with.


{
	"<name>": {
		"name": <string>,
		"klass": <function>,
		"priority": <number>
	},
	"<name>": {
		"name": <string>,
		"klass": <function>,
		"priority": <number>
	},
	...
}
Details
Object.<string, Object>

Methods


contains( name ) → {boolean}

Checks if the factory contains a class registered using the supplied name.

Parameters
Name Type Description
name string

The name of the class to check.

Returns
Examples

// create a new instance of the factory, this is usually exposed by the class that will be using the factory.
var factory = new FooGallery.utils.Factory();

// create a class to register
function Test(){}

// register the class with the factory with the default priority
factory.register( "test", Test );

// test if the class was registered
console.log( factory.contains( "test" ) ); // => true


load( overrides, arg1 [, ...argN ] ) → {Array.<Object>}

Creates new instances of all registered classes using there registered priority and the supplied arguments.

Description

The class indexes within the result array are determined by the priority they were registered with, the higher the priority the lower the index.

This method is designed to be used when all registered classes share a common interface or base type and constructor arguments.

Parameters
Name Type Attributes Description
overrides Object.<string, function()>

An object containing classes to override any matching registered classes with, if no overrides are required you can pass false or null.

arg1 *

The first argument to supply when creating new instances of all registered classes.

argN * <optional>
<repeatable>

Any number of additional arguments to supply when creating new instances of all registered classes.

Returns

An array containing new instances of all registered classes.

Examples

The following loads all registered classes into an array ordered by there priority.


// create a new instance of the factory, this is usually exposed by the class that will be using the factory.
var factory = new FooGallery.utils.Factory();

// create a base Extension class
var Extension = FooGallery.utils.Class.extend({
	construct: function( type, options ){
		this.type = type;
		this.options = options;
	},
	getType: function(){
		return this.type;
	}
});

// create various item, this would usually be in another file
var MyExtension1 = Extension.extend({
	construct: function(options){
		this._super( "my-extension-1", options );
	}
});
factory.register( "my-extension-1", MyExtension1, 0 );

// create various item, this would usually be in another file
var MyExtension2 = Extension.extend({
	construct: function(options){
		this._super( "my-extension-2", options );
	}
});
factory.register( "my-extension-2", MyExtension2, 1 );

// load all registered classes according to there priority passing the options to all constructors
var loaded = factory.load( null, {"something": true} );

// only two classes should be loaded
console.log( loaded.length ); // => 2

// the MyExtension2 class is loaded first due to it's priority being higher than the MyExtension1 class.
console.log( loaded[0] instanceof MyExtension2 && loaded[0] instanceof Extension ); // => true
console.log( loaded[1] instanceof MyExtension1 && loaded[1] instanceof Extension ); // => true

// do something with the loaded classes

The following loads all registered classes into an array ordered by there priority but uses the overrides parameter to swap out one of them for a custom implementation.


// create a new instance of the factory, this is usually exposed by the class that will be using the factory.
var factory = new FooGallery.utils.Factory();

// create a base Extension class
var Extension = FooGallery.utils.Class.extend({
	construct: function( type, options ){
		this.type = type;
		this.options = options;
	},
	getType: function(){
		return this.type;
	}
});

// create a new extension, this would usually be in another file
var MyExtension1 = Extension.extend({
	construct: function(options){
		this._super( "my-extension-1", options );
	}
});
factory.register( "my-extension-1", MyExtension1, 0 );

// create a new extension, this would usually be in another file
var MyExtension2 = Extension.extend({
	construct: function(options){
		this._super( "my-extension-2", options );
	}
});
factory.register( "my-extension-2", MyExtension2, 1 );

// create a custom extension that is not registered but overrides the default "my-extension-1"
var UpdatedMyExtension1 = MyExtension1.extend({
	construct: function(options){
		this._super( options );
		// do something different to the original MyExtension1 class
	}
});

// load all registered classes but swaps out the registered "my-extension-1" for the supplied override.
var loaded = factory.load( {"my-extension-1": UpdatedMyExtension1}, {"something": true} );

// only two classes should be loaded
console.log( loaded.length ); // => 2

// the MyExtension2 class is loaded first due to it's priority being higher than the UpdatedMyExtension1 class which inherited a priority of 0.
console.log( loaded[0] instanceof MyExtension2 && loaded[0] instanceof Extension ); // => true
console.log( loaded[1] instanceof UpdatedMyExtension1 && loaded[1] instanceof MyExtension1 && loaded[1] instanceof Extension ); // => true

// do something with the loaded classes


make( name, arg1 [, ...argN ] ) → {Object}

Create a new instance of a class registered with the supplied name and arguments.

Parameters
Name Type Attributes Description
name string

The name of the class to create.

arg1 *

The first argument to supply to the new instance.

argN * <optional>
<repeatable>

Any number of additional arguments to supply to the new instance.

Returns
Examples

The following shows how to create a new instance of a registered class.


// create a new instance of the factory, this is usually done by the class that will be using it.
var factory = new FooGallery.utils.Factory();

// create a Logger class to register, this would usually be in another file
var Logger = FooGallery.utils.Class.extend({
	write: function( message ){
		console.log( "Logger#write: " + message );
	}
});

factory.register( "logger", Logger );

// create a new instances of the class registered as "logger"
var logger = factory.make( "logger" );
logger.write( "My message" ); // => "Logger#write: My message"


names( [ prioritize ] ) → {Array.<string>}

Gets an array of all registered names.

Parameters
Name Type Attributes Default Description
prioritize boolean <optional>
false

Whether or not to order the names by the priority they were registered with.

Returns
Examples

// create a new instance of the factory, this is usually exposed by the class that will be using the factory.
var factory = new FooGallery.utils.Factory();

// create some classes to register
function Test1(){}
function Test2(){}

// register the classes with the factory with the default priority
factory.register( "test-1", Test1 );
factory.register( "test-2", Test2, 1 );

// log all registered names
console.log( factory.names() ); // => ["test-1","test-2"]
console.log( factory.names( true ) ); // => ["test-2","test-1"] ~ "test-2" appears before "test-1" as it was registered with a higher priority


register( name, klass [, priority ] ) → {boolean}

Registers a klass constructor with the factory using the given name.

Description

Once a class is registered you can use either the load or make methods to create new instances depending on your use case.

Parameters
Name Type Attributes Default Description
name string

The friendly name of the class.

klass function

The class constructor to register.

priority number <optional>
0

This determines the index for the class when using either the load or names methods, a higher value equals a lower index.

Returns

true if the klass was successfully registered.

Examples

// create a new instance of the factory, this is usually exposed by the class that will be using the factory.
var factory = new FooGallery.utils.Factory();

// create a class to register
function Test(){}

// register the class with the factory with the default priority
var succeeded = factory.register( "test", Test );

console.log( succeeded ); // => true
console.log( factory.registered.hasOwnProperty( "test" ) ); // => true
console.log( factory.registered[ "test" ].name === "test" ); // => true
console.log( factory.registered[ "test" ].klass === Test ); // => true
console.log( factory.registered[ "test" ].priority === 0 ); // => true


<static> extend( [ definition ] ) → {function}

Creates a new class that inherits from this one which in turn allows itself to be extended.

Description

Every class created using this method has both the extend and override static methods added to it to allow it to be extended.

Parameters
Name Type Attributes Description
definition Object <optional>

An object containing any methods to implement/override.

Returns

A new class that inherits from the base class.

Examples

The below shows an example of how to implement inheritance using this method.


// create a base Person class
var Person = FooGallery.utils.Class.extend({
	construct: function(isDancing){
		this.dancing = isDancing;
	},
	dance: function(){
		return this.dancing;
	}
});

var Ninja = Person.extend({
	construct: function(){
		// Call the inherited version of construct()
		this._super( false );
	},
	dance: function(){
		// Call the inherited version of dance()
		return this._super();
	},
	swingSword: function(){
		return true;
	}
});

var p = new Person(true);
console.log( p.dance() ); // => true

var n = new Ninja();
console.log( n.dance() ); // => false
console.log( n.swingSword() ); // => true
console.log(
	p instanceof Person && p.constructor === Person && p instanceof FooGallery.utils.Class
	&& n instanceof Ninja && n.constructor === Ninja && n instanceof Person && n instanceof FooGallery.utils.Class
); // => true


<static> override( name, fn )

Overrides a single method on this class.

Description

This is a helper method for overriding a single function of a FooGallery.utils.Class or one of its child classes. This uses the FooGallery.utils.fn.addOrOverride method internally and simply provides the correct prototype.

Parameters
Name Type Description
name string

The name of the function to override.

fn function

The new function to override with, the _super method will be made available within this function.

Examples

The below example wraps the Person.prototype.dance method with a new one that inverts the result. Note the override applies even to instances of the class that are already created.


var Person = FooGallery.utils.Class.extend({
  construct: function(isDancing){
    this.dancing = isDancing;
  },
  dance: function(){
    return this.dancing;
  }
});

var p = new Person(true);
console.log( p.dance() ); // => true

Person.override("dance", function(){
	// Call the original version of dance()
	return !this._super();
});

console.log( p.dance() ); // => false