javascript设计模式-代理
代理是一个对象,它可以用来控制对另一对象的访问。它与另一个对象实现同样的接口,并且会把任何方法调用传递给那个对象。另外那个对象通常称为本体。代理可以代替其本体被实例化,并使其可被远程访问。它还可以把本体的实例化推迟到真正需要的时候。
对于实例化比较费时的本体,或尺寸比较大以至于不用时不宜保存在内存中的本体这特别有用。另外在处理那些需要较长时间才能把数据载入用户界面的类时,代理也非常有用。代理最适合的场景就是创建一个开销昂贵的资源访问。
简单的代理-不太常用
这个例子没有什么实际的作用,可以做为优化的预留接口。
虚拟代理-常用
在用到时再实例化本体,其网页加载时可能没办法一步初始化PublicLibrary。在第一次调用时才会实例化,这可能会导致第一次调用时时间会比较慢。
var PublicLibraryVirtualProxy = function(catalog) { // implements Library this.library = null; this.catalog = catalog; // Store the argument to the constructor. }; PublicLibraryVirtualProxy.prototype = { _initializeLibrary: function() { if(this.library === null) { this.library = new PublicLibrary(this.catalog); } }, findBooks: function(searchString) { this._initializeLibrary(); return this.library.findBooks(searchString); } };通用代理模式
一般用来处理加载数据量或处理比较慢的程序,可以在加载前显示正在处理等字样。它们的缺点就是掩盖了本体的大量细节,而且可以直接和本体互换。所以最好是高质量的文档化。
var DynamicProxy = function() { this.args = arguments; this.initialized = false; if(typeof this.class != 'function') { throw new Error('DynamicProxy: the class attribute must be set before ' + 'calling the super-class constructor.'); } // Create the methods needed to implement the same interface. for(var key in this.class.prototype) { // Ensure that the property is a function. if(typeof this.class.prototype[key] !== 'function') { continue; } // Add the method. var that = this; (function(methodName) { that[methodName] = function() { if(!that.initialized) { return } return that.subject[methodName].apply(that.subject, arguments); }; })(key); } }; DynamicProxy.prototype = { _initialize: function() { this.subject = {}; //触发本体的实例化过程. this.class.apply(this.subject, this.args); this.subject.__proto__ = this.class.prototype; var that = this;//每隔一段时间触发一次,一旦实例化完成,则会阻止本体的一切方法调用 this.interval = setInterval(function() { that._checkInitialization(); }, 100); }, _checkInitialization: function() { if(this._isInitialized()) { clearInterval(this.interval); this.initialized = true; } }, _isInitialized: function() { // Must be implemented in the subclass. throw new Error('Unsupported operation on an abstract class.'); } }; var TestProxy = function() { this.class = TestClass; var that = this; addEvent($('test-link'), 'click', function() { that._initialize(); }); // Initialization trigger. TestProxy.superclass.constructor.apply(this, arguments); }; extend(TestProxy, DynamicProxy); TestProxy.prototype._isInitialized = function() { ... // Initialization condition goes here. };