Facade Pattern

The facade is a simple interface that is shown to the public to hide the complexity of the underlying system

  • they conceal the implementation
  • It is a structural pattern that simplifies the use of your API
  • It also shields developers from being locked to an architecture (can change the internals while keeping the look the same to the public)
  • It has been used for a long time in JavaScript, ever since frameworks wrapped a simple interface around the disparate browser API’s

Step 1 – Page: processor.js


// JavaScript Document
define(function() {
	'use strict';
	
	return { //module returns an API of 5 methods that each deal with a different data type.  This is just for example, the processing isn't complex or necessarily useful.  Module doesn't depend on facade, just exposes the API methods.  It could have dependencies with other modules, but should never depend on facade.  Facade depends on this.
		processString: function (string) { 
			return string.substring(0, string.length / 2);
		},
		processNumber: function (number) {
			return number * number;
		},
		processBoolean: function (bool) {
			return !bool;
		},
		processArray: function (array) {
			return array.length;
		},
		processObject: function (object) {
			return Object.keys(object).length;	
		}
	};
});

Step 2 – Page: facade.js


// JavaScript Document
define(function(require) { //must use require function to load the processor module
	'use strict';
	
	var processor = require('facade/processor'); //load the processor as a dependency
	
	return { //return the single method contained by the facade
		processData: function (data) { //this is the method exposed by the facade
			switch (Object.prototype.toString.call(data)) { //in this method, we use a switch statement to invoke a processor method depending on the data type passed to the facade.  Value that we switch upon is the data type.  We use object.prototype.toString.call method to convert data type to object String, object Number, object Boolean, etc.  We then switch on this
				case '[object String]':
					return processor.processString(data);
					break;
				case '[object Number]':
					return processor.processNumber(data);
					break;	
				case '[object Boolean]':
					return processor.processBoolean(data);
					break;
				case '[object Array]':
					return processor.processArray(data);
					break;
				case '[object Object]':
					return processor.processObject(data);
					break;
				default:
					return 'Unable to process the data';
			}
		}
	};
});

Step 3 – init.js


define(function(require) {
	'use strict';

	return {
		init: function() {
			var facade = require('facade/facade'); //add the facade as a dependency
			
			console.log(facade.processData('test string')); //log out a bunch of statements
			console.log(facade.processData(5));
			console.log(facade.processData(false));
			console.log(facade.processData([1, 2, 3]));
			console.log(facade.processData({prop: 'something', other: 'else'}));
		} //this init file is nicely decoupled from processor.  Processor can be refactored as needed, as long as API methods are the same
	};
});

Step 4 – main.js


// JavaScript Document
require (
	['facade/init'],
	function ( facade) {
			'use strict';
	
			var examples = {
					
					facade: facade
				};
			
			window.runExample = function (example) {
				examples[example].init();
			};
	}
);

Conclusion

With a facade, we can hide the complexity of the underlying system and just expose a way to interact with the system. It presents a simplified API as the means of working with the application. The subsystems (or modules like the processor) can be changed or refactored as necessary, as long as the API methods remain the same.