In the simplest terms, the pattern starts with a function:
function stuff(s){ if (typeof s == 'string') doStuffWithAString(s) else throwOrIgnore(); }
Maybe you can't change the source code, or maybe you obsessively want to ultra-modularize your code. Either way, assume you want to use the same name to keep your source code as semantic as possible. Here is how I would do it:
// redefine function var _old_stuff = stuff; stuff = function(b){ // check for special case which should be overloaded here if (typeof b == 'boolean') // new behavior doStuffWithABoolean(b); // old behavior: call previously defined function. else _old_stuff(b); };
If you happen to mistakenly call the block twice, you will throw the function into a self-referential (endless) loop.
With this pattern, you can build functions that specialize in delegating functions by argument patterns, akin to classical Java method overloading. If you will be handling many patterns, it may eventually be interesting to use only one index delegator instead of a cascading pattern.
To illustrate how amusing it is to write overcomplicated code, consider the following
Mega Super Ultimate Listener Overload Pattern of Awesomeness
The interface is the only public function:
function transmogrify(){ // using this function as a dictionary or map: for (var filter in transmogrify.filters){ // filter functions return the name of the method to call var key = transmogrify.filters[filter].apply(this, arguments); if (key) transmogrify.methods[key].apply(this, arguments); } }
This is the extension mechanism. The filter can check argument arity, type, validity, etc.
transmogrify.filters.zap = function(str, num){ if (typeof str == 'string' && typeof num == 'num') return 'zip'; }; transmogrify.methods.zip = function(){ // there be beautiful code herein };
I know you want a function that does these two things in one go; a meta-meta-meta function. Maybe later.
No comments:
Post a Comment