// Abstract Factory
/*
({}).createInstance()
(function (a, b, c) {
this.sum = a + b + c;
}).createInstance([1, 2, 3])
*/
Object.defineProperty(
// (C) WebReflection - Mit Style License
Object.prototype,
"createInstance",
{
value: (function (create) {
return function createInstance(args) {
var
self = this,
isFunction = typeof self == "function",
obj = create(isFunction ? self.prototype : self)
;
isFunction && args != null && self.apply(obj, args);
return obj;
};
}(Object.create))
}
);
// Abstract Builder
/*
var person = Object.builder({
setup: function (name) {
this.create();
this.instance.name = name;
}
});
person.setup("WebReflection");
alert(person.instance.name);
person.create();
person.instance.name = "Andrea";
alert(person.instance.name);
*/
Object.defineProperty(
// (C) WebReflection - Mit Style License
Function.prototype,
"builder",
{
value: function (methods) {
var
$create = Object.create,
self = this,
proto = self.prototype,
obj
;
return $create(methods, {
instance: {
get: function get() {
return obj;
}
},
create: {
value: function create() {
obj = $create(proto);
self.apply(obj, arguments);
}
}
});
}
}
);
// Multiton + Singleton pattern
// (via lazy initialization)
/*
function Car(){}
var car = Car.getInstance();
alert(car === Car.getInstance());
alert(car !== Car.getInstance("bmw"));
alert(Car.getInstance("bmw") === Car.getInstance("bmw"));
*/
Object.defineProperty(
// (C) WebReflection - Mit Style License
Function.prototype,
"getInstance",
{
value: function (key) {
var
create = Object.create,
instances = {},
self = this,
proto = self.prototype,
instance
;
Object.defineProperty(
self,
"getInstance",
{
value: function getInstance(key) {
return key == null ?
instance || (instance = create(proto)) :
instances.hasOwnProperty(key) ?
instances[key] :
instances[key] = create(proto)
;
}
}
);
return self.getInstance(key);
}
}
);
// Prototype
/*
var definition = {some:"thing"};
var inherited = Object.create(definition);
*/
Object.create;
// Abstract Adapter
/*
function Person() {}
Person.prototype.setName = function setName(_name) {
this._name = _name;
};
var getter = {
toString: function () {
return this._name;
}
};
var me = {};
me.adapt(Person);
me.setName("WebReflection");
me.adapt(getter);
alert(me);
*/
Object.defineProperty(
// (C) WebReflection - Mit Style License
Object.prototype,
"adapt",
{
value: (function (proto) {
return proto in {} ?
function adapt(Class) {
this[proto] = typeof Class == "function" ? Class.prototype : Class;
} :
function adapt(Class) {
var self = this;
typeof Class == "function" && Class = Class.prototype;
for (proto in Class)
self.hasOwnProperty(proto) || (self[proto] = Class[proto])
;
}
;
}("__proto__"))
}
);
// Abstract Composite
/*
function AddToBody(value) {
this.value = value;
}
AddToBody.prototype.value = "";
AddToBody.prototype.exec = function () {
document.body.appendChild(
document.createElement("p")
).innerHTML = this.value;
};
var many = AddToBody.composite();
many.push(
new AddToBody("this"),
new AddToBody("is"),
new AddToBody("a"),
new AddToBody("test")
);
this.onload = function () {
many.exec();
alert(many.value);
many.value = "everybody like this";
many.exec();
alert(many.value);
};
*/
Object.defineProperty(
// (C) WebReflection - Mit Style License
Function.prototype,
"composite",
{
value: (function (defineProperty) {
return function composite() {
function get(key) {
function retrieve(item) {
return item[key];
}
return function get() {
return map.call(this, retrieve);
};
}
function set(key) {
function assign(item) {
item[key] = this;
}
return function set(value) {
forEach.call(this, assign, value);
};
}
function wrap(method) {
function apply(item) {
method.apply(item, this);
}
return function wrap() {
forEach.call(this, apply, arguments);
};
}
var
composite = [],
forEach = composite.forEach,
map = composite.map,
proto = this.prototype,
key, value
;
for (key in proto) {
if (typeof(value = proto[key]) == "function") {
composite[key] = wrap(value);
} else {
defineProperty(
composite,
key,
{
get: get(key),
set: set(key)
}
);
}
}
return composite;
};
}(Object.defineProperty))
}
);
// Observer/Listener
/*
function hello(e) {
alert(e.type);
}
var obj = new Listener;
obj.addEvent("hello", hello);
obj.addEvent("hello", hello);
obj.fireEvent("hello");
obj.fireEvent({type:"hello"});
obj.removeEvent("hello", hello);
obj.fireEvent({type:"hello"});
*/
var Listener = (function () {
// (C) WebReflection - Mit Style License
function Listener() {
handler.value = {};
defineProperty(this, "_handler", handler);
}
function fire(callback) {
callback.call(this.target, this);
}
var
proto = Listener.prototype
defineProperty = Object.defineProperty,
handler = {
value: proto
},
empty = []
;
Object.defineProperties(
Listener.prototype,
{
addEvent: {
value: function addEvent(type, callback) {
var stack = this._handler[type] || (this._handler[type] = []);
stack.indexOf(callback) < 0 && stack.push(callback);
}
},
removeEvent: {
value: function removeEvent(type, callback) {
var
stack = this._handler[type] || empty,
i = stack.indexOf(callback)
;
-1 < i && stack.splice(i, 1);
}
},
fireEvent: {
value: function fireEvent(e) {
typeof e == "string" && (e = {type: e});
e.target = this;
(this._handler[e.type] || empty).forEach(fire, e);
}
}
}
);
return Listener;
}());
behind the design
My JavaScript book is out!
Don't miss the opportunity to upgrade your beginner or average dev skills.
Showing posts with label Factory. Show all posts
Showing posts with label Factory. Show all posts
Monday, December 27, 2010
ES5 Common Design Patterns Examples - Part 1
Monday, January 18, 2010
Good Old And Common JavaScript Errors
... I won't write any introduction, but I'll let you comment, OK?
Few people told me something like: "doode, if you use ++i at the end you need to write i < 11 'cause i will be 1 inside the loop" ... basically the for loop has been rarely understood, let me try again:
The reason ++i is preferred over i++, whatever Google go language decided about it, is that i++ and ++i are totally different and you need to understand when, or why, you need i++ or ++i.
While ++i increments directly the variable, returning the variable itself, if numeric, i++ returns a NEW variable with the precedent value AND it increments the i var as well.
Pure JavaScript Example
It does not matter if speed speaking, the difference is "not that consistent", it matters that we are programmer, and if two things mean different things, we want to understand them, am I wrong?
Another piece of code you can find around the net, is this:
Above code will never work, and it's the ABC about scope and functions.
It's exactly like this:
Same is for arguments:
What we need to understand, is that next code is ALWAYS true:
The moment we define a scoped variable, it has precedence over whatever outer scope: bear in mind!!!
I can't wait the day people will stop to prefer this code:
rather than:
There are no excuses at all. First of all, the "new Array/Object" way is unsafe, since both constructors can be easily redefined/wrapped, as explained ages ago in many different security related JavaScript issues.
Moreover, we have both more bytes to digest and reduced performance, and a compiler/minifier that is so cool that will change automatically new Array into [] will simply potentially break our code so we cannot even rely improvements with production code.
So ... PLEASE DON'T!
Would you ever use in your Java life a factory method via "new" ???
Seriously, I don't get it ... let's go one step back ...
Same is for no returns, or return undefined.
If a JavaScript function returns an object, the usage of new is completely redundant and useless.
As summary, and again, please repeat with me:
This is the most misunderstood part that seems so logical but does not make sense at all. 99.9% of cases and in different libraries we can find the classic call to new Class to create what people think is a Class in JavaScript (in few words, to populate the prototype of a runtime created function).
Wait a second ... did I just say: to create a Class?
Uhm ... so, we don't create an instance ... we create a class ... uhm again, so, we are using a Factory, isn't it? :zizi:
Function.createClass() would be hundreds of times more correct, logically speaking, but we all like the new Class, right?
Well, I wonder how many Java Gurus create they Java classes via new Class() on daily basis ... what? You have to define a class, not to create one? ... oh, REALLY???
MooTools use new Class to create runtime functions, parse the configuration object in order to populate the created function prototype, extending it with a completely useless this, that could be simply Class.prototype without useless runtime instanc`es creation for each Class, to finally return a function that is not instanceof Class ... not even primitives values in JavaScript are that ambiguous, isn't it?
MooTools is simply one in the ocean of libraries that use this misconception to create Functions, not Class, Function.
Considering that JavaScript has no classes, something apparently unacceptable for GWT and friends maniacs that absolutely need to compile their Java application inevitably into a prototypal based programming language as JavaScript is, thinking they have more power over the application, I agree that classic OOP is something so intrinsic in the IT panorama, that it will never die and it could make somehow things simpler for newcomers into JavaScript. OK, I am with you ... can we at least agree about the fact new factoryMethod does not make sense at all?
Rather than nonsense why don't we simply respect JavaScript native behavior?
If we consider native constructors behaviors such Boolean, Number, or String, I have already described what's up if we use new or not.
There is a massive difference between new and not new ... so why don't use the same behavior for Funciton?
In few words we can easily think about Function as a primitive function creator AND as a function instances creator, those that we'll love to use to instantiate our application objects. Does it sound really that silly?
Here we are, and the best thing is that we can extend the prototype chain simply passing another prototype as configuration object.
Moreover, since whatever library will use a Function to create other functions, but since most of the time the new Class won't return an instanceof Class, with my suggestion whatever created "Class" will simply inherit Function.prototype.methods OR, if we want to add custom public methods, we can always do it later.
Finally, with a simple closure, we can still be semantic, and define private methods:
Now it's your turn, feel free to comment the path I followed, and give me other suggestions/common errors, if you remember any ;)
Update I almost forgot one of the most famous/silly one ...
Another common mistake is to think that "for in" is good for arrays.
First of all the iteration order is unpredictable, there is no rule about "for in" iteration (or if any, nothing that is standard, cross-browser speaking) plus it's way slower than a normal iteration via length. Please DON'T!!! In this case as well.
for loops (plus ++i)
for(i = 0; i < 10; i++){}
// global i defined
for(var i = 0; i < something.length; i++){}
// cache the length if it won't change during the loop
// associate once only under certain conditions to speed up
for(var i = 0; i < 10; ++i) {}
// there is absolutely nothing wrong in above loop
Few people told me something like: "doode, if you use ++i at the end you need to write i < 11 'cause i will be 1 inside the loop" ... basically the for loop has been rarely understood, let me try again:
// directly from C language, 1972
for(
// optional inline declaration, coma accepted for more vars
;
// optional condition to verify
// if undefined, it loops until a break is encountered
// this condition is performed BEFORE the first loop
// if false, the loop will never be executed
;
// optional POST operation, it will never be executed
// if the condition is false, "", 0, or null
// it is executed in any case AFTER the loop, if any
){};
// example
for(var i = 0; i < 1; ++i){
// one single execution
// i will be 0 here
};
// i will be 1 here
The reason ++i is preferred over i++, whatever Google go language decided about it, is that i++ and ++i are totally different and you need to understand when, or why, you need i++ or ++i.
While ++i increments directly the variable, returning the variable itself, if numeric, i++ returns a NEW variable with the precedent value AND it increments the i var as well.
Pure JavaScript Example
function Num(value) {
this.value = value;
};
Num.prototype.valueOf = function () {
return new Num(this.value);
};
Num.prototype.toString = function () {
return "" + this.value;
};
var a = new Num(0);
var b = a++;
alert(a); // 1
alert(b); // 0
alert(a == b); // false
// again
var a = new Num(0);
var b = ++a;
alert(a); // 1
alert(b); // 1
alert(a == b); // true
It does not matter if speed speaking, the difference is "not that consistent", it matters that we are programmer, and if two things mean different things, we want to understand them, am I wrong?
Already defined variables, and scopes
Another piece of code you can find around the net, is this:
// something defined globally
var num = 1;
(function () {
// try to set a default
var num = num || 0;
})();
Above code will never work, and it's the ABC about scope and functions.
It's exactly like this:
// something defined globally
var num = 1;
(function (num) {
// now try to find the global num without this. or window. ...
})();
function A() {
// this is actually correct since arguments shares same scope
// no shadowing in this case, thanks to qfox
var arguments = arguments || [];
};
What we need to understand, is that next code is ALWAYS true:
var u = 123;
(function () {
var u = (typeof u === "undefined");
// u is TRUE!!!
})();
The moment we define a scoped variable, it has precedence over whatever outer scope: bear in mind!!!
new Array, new Object
I can't wait the day people will stop to prefer this code:
var a = new Array(); // NOTE: no length/elements specified
var o = new Object(); // NOTE: no object to wrap/convert
rather than:
var a = [];
var o = {};
There are no excuses at all. First of all, the "new Array/Object" way is unsafe, since both constructors can be easily redefined/wrapped, as explained ages ago in many different security related JavaScript issues.
Moreover, we have both more bytes to digest and reduced performance, and a compiler/minifier that is so cool that will change automatically new Array into [] will simply potentially break our code so we cannot even rely improvements with production code.
So ... PLEASE DON'T!
... and new Function ...
Hey, Java guys, please answer this question:Would you ever use in your Java life a factory method via "new" ???
Seriously, I don't get it ... let's go one step back ...
The Meaning of Factory
The essence of the Factory Pattern is to "Define an interface for creating an object, but let the subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses."
JavaScript Functions Behavior
If a JavaScript function returns a primitive value such: "string", true, false, null, int, double, new function will return an instanceof that function, overriding the returned result.Same is for no returns, or return undefined.
If a JavaScript function returns an object, the usage of new is completely redundant and useless.
Array, Function, Object, and RegExp are Factory!!!
var a = Array();
var b = new Array();
var c = [];
[
a instanceof Array,
b instanceof Array,
c instanceof Array
]; // true,true,true
Boolean, Date, Number, and String are both primitive casts and Object constructors!!!
var a = 1;
var b = Number("1");
var o = new Number(1);
a === b; // true
a === o; // false
a == o; // true
a instanceof Number; // false
o instanceof Number; // true
typeof a; // number
typeof o; // object
As summary, and again, please repeat with me:
If a JavaScript function returns a primitive value such: "string", true, false, null, int, double, new function will return an instanceof that function, overriding the returned result.
If a JavaScript function returns an object, the usage of new is completely redundant and useless.
new Class(whatever) === new Factory(whatever)!!!
This is the most misunderstood part that seems so logical but does not make sense at all. 99.9% of cases and in different libraries we can find the classic call to new Class to create what people think is a Class in JavaScript (in few words, to populate the prototype of a runtime created function).
Wait a second ... did I just say: to create a Class?
Uhm ... so, we don't create an instance ... we create a class ... uhm again, so, we are using a Factory, isn't it? :zizi:
Function.createClass() would be hundreds of times more correct, logically speaking, but we all like the new Class, right?
Well, I wonder how many Java Gurus create they Java classes via new Class() on daily basis ... what? You have to define a class, not to create one? ... oh, REALLY???
MooTools use new Class to create runtime functions, parse the configuration object in order to populate the created function prototype, extending it with a completely useless this, that could be simply Class.prototype without useless runtime instanc`es creation for each Class, to finally return a function that is not instanceof Class ... not even primitives values in JavaScript are that ambiguous, isn't it?
new Class({}) instanceof Class; // FALSE!!!
MooTools is simply one in the ocean of libraries that use this misconception to create Functions, not Class, Function.
Considering that JavaScript has no classes, something apparently unacceptable for GWT and friends maniacs that absolutely need to compile their Java application inevitably into a prototypal based programming language as JavaScript is, thinking they have more power over the application, I agree that classic OOP is something so intrinsic in the IT panorama, that it will never die and it could make somehow things simpler for newcomers into JavaScript. OK, I am with you ... can we at least agree about the fact new factoryMethod does not make sense at all?
Logically Speaking ...
Rather than nonsense why don't we simply respect JavaScript native behavior?
If we consider native constructors behaviors such Boolean, Number, or String, I have already described what's up if we use new or not.
There is a massive difference between new and not new ... so why don't use the same behavior for Funciton?
// example
var f = Function("return 'function'");
alert([f instanceof Function, f()]);
// true,function
var f = new Function({toString:function(){return "instance"}});
alert([f instanceof Function, new f()]);
// true,instance
In few words we can easily think about Function as a primitive function creator AND as a function instances creator, those that we'll love to use to instantiate our application objects. Does it sound really that silly?
var Function = (function (Function) {
// (C) WebReflection Mit Style
// Class with private constructor
function constructor(constructor) {
function Class() {
constructor.apply(this, arguments);
};
return Class;
};
// Class creator
function Class(__proto__) {
function Class() {};
if (__proto__) {
if (hasOwnProperty.call(__proto__, "constructor")) {
Class = constructor(__proto__.constructor);
};
(Class.prototype = clone(__proto__)).constructor = Class;
};
return Class;
};
// special Function
function $Function(arguments, body) {
return this instanceof Function ?
Class(arguments) :
body == null ? Function(arguments) : Function(arguments, body)
;
};
// private variables
var
hasOwnProperty = Object.prototype.hasOwnProperty,
clone = Object.clone || (function () {
function clone() {};
return function (__proto__) {
clone.prototype = __proto__;
return new clone;
};
})()
;
// public static explicit factory
$Function.create = Function;
$Function.createClass = Class;
$Function.prototype = Function.prototype;
return $Function;
})(Function);
Here we are, and the best thing is that we can extend the prototype chain simply passing another prototype as configuration object.
function A(){};
var B = new Function(A.prototype);
alert(new B instanceof A); // true
Moreover, since whatever library will use a Function to create other functions, but since most of the time the new Class won't return an instanceof Class, with my suggestion whatever created "Class" will simply inherit Function.prototype.methods OR, if we want to add custom public methods, we can always do it later.
Finally, with a simple closure, we can still be semantic, and define private methods:
var MyClass = new Function((function () {
function set(value) {
this.value = value;
};
return {
constructor:function (value) {set.call(this, value)},
get:function () {return this.value}
};
})());
var o = new MyClass(123);
alert(o.get()); // 123
Now it's your turn, feel free to comment the path I followed, and give me other suggestions/common errors, if you remember any ;)
Update I almost forgot one of the most famous/silly one ...
Arrays "for in"
var a = [];
a[1] = 1;
a[0] = 0;
// global key defined
for(key in a);
// key will be first 1, then zero, in Internet Explorer and Opera
for(var key in a);
Another common mistake is to think that "for in" is good for arrays.
First of all the iteration order is unpredictable, there is no rule about "for in" iteration (or if any, nothing that is standard, cross-browser speaking) plus it's way slower than a normal iteration via length. Please DON'T!!! In this case as well.
Thursday, June 19, 2008
A completely revisited Singleton and Factory design pattern for PHP and JavaScript
Singleton
From Wikipedia
In software engineering, the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. Sometimes it is generalized to systems that operate more efficiently when only one or a few objects exist. It is also considered an anti-pattern by some people, who feel that it is often used as a euphemism for global variable
Basically, the last point is true.
Whatever we think about Singleton, we cannot say that we do not use this pattern to have the same instance, or object, in every place of our application.
The most common case scenario, is usually a database object, or a global queue, used as a stack, or something similar, like a template engine instance or a DOM / XML node.
The worst thing ever, is that with languages like PHP and JavaScript, the Singleton pattern is really hard to implement correctly.
Why bother with a class?
In a lot of frameworks, as in a lot of libraries, I have seen every kind of Singleton implementation, and most of them, are conceptually hilarious.
// PHP Singleton classic example
Singleton::load('MyCLassName');
MyClassName::getInstance();
// JavaSript classic example
MyConstructor.getInstance();
// where in different cases, getInstance
// is not even defined inside a closure
// to preserve singleton integrity ...
// ... but does exist a way to make
// a JS constructor private? NO
With PHP, problems are different:
- if there's no magic __clone method, it does not make sense
- if you serialize and unserialize objects, it could not make sense
- if you create a Singleton class, it is nearly impossible to extend correctly its behaviour (come on lazy binds and PHP 5.3!!!)
- if you try to create a __callStatic method, you simply have to wait next PHP release
In PHP again, as is for JavaScript, outside a closure, every static function is global.
This means that we do not need to use global something, in PHP, and we do not use, usually, window as prefix to use declared function.
It is true, the most horrible piece of code you can spot in an entire PHP application, is the usage of global keyword to transport variables everywhere.
We do not need that, and we can have a Singleton behaviour, simply using a function !!!
function Singleton($__CLASS__){
// webreflection.blogspot.com
static $list = array();
if(!isset($list[$__CLASS__])){
$arguments = func_get_args();
array_shift($arguments);
$instance = new ReflectionClass($__CLASS__);
$list[$__CLASS__] = $instance->getConstructor() ? $instance->newInstanceArgs($arguments) : $instance->newInstance();
}
return $list[$__CLASS__];
}
Is static variable private inside function scope? Yes
Is this function smarter than a public static method? Yes
class A {
protected $value = '123';
function write($what){
echo $what.$this->value;
return $this;
}
}
class B extends A {
function __construct($value){
$this->value = $value;
}
}
echo '', var_dump(Singleton('A') === Singleton('A')), '';
echo '', var_dump(';
Singleton('B', 'my value')->write('Hello World') === Singleton('B')
), '
// true, Hello Worldmy value, true
Do you really want a class?
Ok, somebody could thing that above function is pointless, so here there is a class that will use the same function.
class Singleton {
// webreflection.blogspot.com
private $_class,
$_instance;
public function __construct($__CLASS__){
$arguments = func_get_args();
$this->_class = new ReflectionClass($this->_instance = call_user_func_array('Singleton', $arguments));
}
public function __get($property){
return $this->_instance->$property;
}
public function __call($method, array $arguments){
return $this->_class->getMethod($method)->invokeArgs($this->_instance, $arguments);
}
public function __set($property, $value){
$this->_instance->$property = $value;
}
public function equal($_instance){
return $_instance instanceof Singleton ? $this->_instance === $_instance->_instance : $this->_instance === $_instance;
}
}
With above class, using the Singleton function as well, you can even use the new keyword to obtain every time the same instance.
$b = new Singleton('B', 'my value');
echo '', var_dump(';
$b->equal(Singleton('B')->write('Hello World')) &&
$b->equal(new Singleton('B'))
), '
Well, at this point we have the shortest way to obtain the same behaviour, using, or not, a class.
Factory
From Wikipedia
The Factory pattern is a creational design pattern used in software development to encapsulate the processes involved in the creation of objects.
The creation of an object often requires complex processes not appropriate to include within a composing object. The object's creation may lead to a significant duplication of code, may require information not accessible to the composing object, may not provide a sufficient level of abstraction, or may otherwise not be part of the composing object's concerns.
Specially in PHP, a Factory pattern is useful to avoid problems with new keyword when you create an object.
For example, this is not possible:
new Class("stuff")->doStuff();
With a Factory behaviour it is natural to do something like this:
Factory('Class')->doStuff();
In those case when we need an instance once, or few times, and never more, to do some super cool computation, we could avoid variable assignment and, in some case, use a function with the same class name as proposed few days ago.
But this time, using exactly the same concept of Singleton, it is even more simple to create a general purpose Factory function:
function Factory($__CLASS__){
// webreflection.blogspot.com
static $list = array();
if(!isset($list[$__CLASS__]))
$list[$__CLASS__] = new ReflectionClass($__CLASS__);
$arguments = func_get_args();
array_shift($arguments);
return $list[$__CLASS__]->getConstructor() ? $list[$__CLASS__]->newInstanceArgs($arguments) : $list[$__CLASS__]->newInstance();
}
Some example?
class A {
public function setName($name){
$this->name = $name;
return $this;
}
}
$me = Factory('A')->setName('Andrea');
echo $me->name; // Andrea
Not every consideration I did for Singleton pattern is true for Factory one, but the structure of the function, as the possible class, is about the same.
At this point, assuming that in my implementation Factory is an extended version of the Singleton, creating more instances than one, you can have a look into the complete source of my Factory and Singleton implementation.
Why there is JavaScript in this post topic?
The reaon is simple, everything I have done with PHP, is simply replicable with JavaScript, but this time, with only 8 lines of code:
// webreflection.blogspot.com
Factory = function(__CLASS__){
for(var i = 1, length = arguments.length, args = new Array(length - 1); i < length; i++)
args[i - 1] = "arguments[" + i + "]";
return Function("return new " + __CLASS__ + "(" + args.join(",") + ")").apply(null, arguments);
};
Singleton = function(list){return function(__CLASS__){
return __CLASS__ in list ? list[__CLASS__] : list[__CLASS__] = Factory.apply(null, arguments);
}}({});
Seems to be simple, isn't it? :geek:
Sunday, June 01, 2008
PHP or JavaScript implicit Factory method design pattern
Update
Above technique could be used to create an implicit Singleton as well.
I have talked about JavaScript possibility different times in my prototypal inheritance documentation, and in other posts of this blog. The summary is that thanks to perfect this behaviour, that for some unknown reason someone would like to modify in JS2, making them ambiguous when you are using a constructor as a function and not, for example, as private method, we can create intelligent constructors that does not require the usage of new keyword - in a Pythonic way:
The main advantage, using this technique, is that we write less code and we are able to concatenate every public method, allowing us to do different stuff in few lines.
We could use simply constructor when we would like to create an instance and use then directly a public method.
Above examples show JavaScript new keyword nature, and its priority when we use brackets around, or at the of the constructor - passing, or not, one or more arguments. With implicit factory method purpose, we could simply do stuff like this one:
To be honest, with native or defined constructors, we should put more effort to implement my proposed technique, but the aim of this post is to show how could be possibile to do the same, with PHP.
I suppose that if you are an Object Oriented PHP Programmer, you have tried, at least once, to do something like this and without success:
Since in PHP both usage of brackets and syntax are different, the "only" way we have to concatenate public methods is to create a manual factory one:
Above example is a very common one in many OO frameworks or libraries.
You probably don't know that thanks to some intrinsic PHP language ambiguity, it is possible to create a function with the same name of a class, as is, for example, for constants, but this time without future features problems.
The PHP interpreter is able to recognize if we are calling the class or the function, simply looking at new keyword.
If we are using them, it will be obviously an instance creation, while if we are not using them, it will be obviously a function call.
The last case is if we do not use brackets, and then it will be the defined constant, if any, or, in a better future, the static public __toString method, if any again.
Since this way to code and use classes and functions could be truly interesting, and since we could have one to thousands of classes, it is natural to think how to automatically implement this kind of feature in our project.
The answer is a function, called __autofactory, that will be able to create a file to include, or require, that will contain every defined class as function, using best practices to speed up implicit factory method usage.
The only thing to write before logic code execution, is this piece of code:
The first parameter will be the name of the file that will contain informations, while the second one will specify, if present and with a false evaluable data, if function should require them or not.
At this point, you have basis and / or code to use this particular feature for every kind of purpose.
Above technique could be used to create an implicit Singleton as well.
class Demo {
// your unbelievable stuff
}
function Demo($some, $arg){
static $instance;
return isset($instance) ? $instance : ($instance = new Demo($some, $arg));
}
Demo(1,2)->doStuff();
Demo(1,2) === Demo(1,2); // true
from Wikipedia
The factory method pattern is an object-oriented design pattern ... More generally, the term factory method is often used to refer to any method whose main purpose is creation of objects.
I have talked about JavaScript possibility different times in my prototypal inheritance documentation, and in other posts of this blog. The summary is that thanks to perfect this behaviour, that for some unknown reason someone would like to modify in JS2, making them ambiguous when you are using a constructor as a function and not, for example, as private method, we can create intelligent constructors that does not require the usage of new keyword - in a Pythonic way:
// JavaScript
function Person(name, age){
if(this instanceof Person){
this.name = name;
this.age = age;
} else
return new Person(name, age);
};
Person.prototype.getInfo = function(){
return this.name + " is " + this.age + " years old";
};
// Example
alert(
Person("Andrea", 30).getInfo() // Andrea is 30 years old
);
var a = Person("Luca", 25),
b = Person("Fabio", 31);
The main advantage, using this technique, is that we write less code and we are able to concatenate every public method, allowing us to do different stuff in few lines.
alert(
Person(name, age).transFormToEmployee(company).getInfo()
);
The new keyword
We could use simply constructor when we would like to create an instance and use then directly a public method.
var time = (new Date).getTime();
// same as
var time = new Date().getTime();
// different of
var time = new Date.getTime(); // Date.getTime is not a constructor !!
Above examples show JavaScript new keyword nature, and its priority when we use brackets around, or at the of the constructor - passing, or not, one or more arguments. With implicit factory method purpose, we could simply do stuff like this one:
// just a basic (and wrong) example of implicit factory implementation
Date = function(Date){
return function(){
return this instanceof Date ? this : new Date;
};
}(Date);
var time = Date().getTime();
To be honest, with native or defined constructors, we should put more effort to implement my proposed technique, but the aim of this post is to show how could be possibile to do the same, with PHP.
PHP implicit Factory method
I suppose that if you are an Object Oriented PHP Programmer, you have tried, at least once, to do something like this and without success:
echo new Person("Me", 30)->getInfo();
echo (new Person("Me", 30))->getInfo();
Since in PHP both usage of brackets and syntax are different, the "only" way we have to concatenate public methods is to create a manual factory one:
class Person {
// ... our stuff ...
static public function create($name, $age){
return new Person($name, $age);
}
}
echo Person::create($name, $age)->getInfo();
Above example is a very common one in many OO frameworks or libraries.
Ambiguity
You probably don't know that thanks to some intrinsic PHP language ambiguity, it is possible to create a function with the same name of a class, as is, for example, for constants, but this time without future features problems.
// PHP
class Person {
function Person($name, $age){
$this->name = $name;
$this->age = $age;
}
function getInfo(){
return "{$this->name} is {$this->age} years old";
}
}
// factory method!!!
function Person($name, $age){
return new Person($name, $age);
}
// Example
echo Person("Andrea", 30)->getInfo(); // Andrea is 30 years old
?>
The PHP interpreter is able to recognize if we are calling the class or the function, simply looking at new keyword.
If we are using them, it will be obviously an instance creation, while if we are not using them, it will be obviously a function call.
The last case is if we do not use brackets, and then it will be the defined constant, if any, or, in a better future, the static public __toString method, if any again.
The __autofactory function
Since this way to code and use classes and functions could be truly interesting, and since we could have one to thousands of classes, it is natural to think how to automatically implement this kind of feature in our project.
The answer is a function, called __autofactory, that will be able to create a file to include, or require, that will contain every defined class as function, using best practices to speed up implicit factory method usage.
The only thing to write before logic code execution, is this piece of code:
// ... application classes inclusions
// before code logic
require '__autofactory.php';
!file_exists($fileName = 'factory.function.php') && __autofactory($fileName);
The first parameter will be the name of the file that will contain informations, while the second one will specify, if present and with a false evaluable data, if function should require them or not.
At this point, you have basis and / or code to use this particular feature for every kind of purpose.
Subscribe to:
Posts (Atom)