JS设计模式——7.工厂模式(示例-RSS阅读器)
RSS阅读器
由于我们只想跟RSS容器对象打交道,所以用一个工厂来实例化这些内部对象并把它们组装到一个RSS阅读器中.
使用工厂方法在好处在于,我们创建的RSS阅读器类不会与那些成员对象紧密耦合在一起.
RSS阅读器的成员对象
成员对象1: xhr
这个对象就是上一篇中介绍过的,所以就不再说了.
成员对象2: 显示类
为了满足RSS阅读器类的需要,它需要实现几个方法.
var DisplayModule = new Interface('DisplayModule', ['append', 'remove', 'clear']); var ListDisplay = function(id, parent){ this.list = document.createElement('ul'); this.list.id = id; parent.appendChild(this.list); }; ListDisplay.prototype = { append: function(text){ var newEl = document.createElement('li'); this.list.appendChild(newEl); newEl.innerHTML = text; return newEl; }, remove: function(el){ this.list.removeChild('el'); }, clear: function(){ this.list.innerHTML = ''; } };
成员对象3: 配置对象
这只是一个对象字面量,它包含着一些借位阅读器类及其成员对象使用的设置
var conf = { id: 'con-top-stories', feedUrl: 'http://www.baidu.com', updateInteval: 60, parent: $('feed-readers') };
RSS阅读对象类
上面介绍的类都由一个名为FeedReader的类组合使用.它用xhr处理器从RSS源获取XML格式的数据并用一个内部方法进行解析,然后用显示模块将解析出来的信息输出到网页上.
var FeedReader = function(display, xhrHandler, conf){ this.display = display; this.xhrHandler = xhrHandler; this.conf = conf; this.startUpdates(); }; FeedReader.prototype = { fetchFeed: function(){ var that = this; var callback = { success: function(text, xml) {that.parseFeed(text, xml)}, failure: function(status) {that.showError(status);} }; this.xhrHandler.request('GET', 'feedProxy.php?feed='+this.conf.feedUrl, callback); }, parseFeed: function(responseText, responseXML){ this.display.clear(); var items = responseXML.getElementsByTagName('item'); for(var i= 0, len=items.length; i<len; i++){ var title = items[i].getElementsByTagName('title')[0]; var link = items[i].getElementsByTagName('link')[0]; this.display.append('<a href="'+link.firstChild.data+'">'+this.firstChild.data+'</a>'); } }, showError: function(statusCode){ this.display.clear(); this.display.append('Error fetching feed.'); }, stopUpdates: function(){ clearInterval(this.interval); }, startUpdates: function(){ this.fetchFeed(); var that = this; this.interval = setInterval(function(){that.fetchFeed();}, this.conf.updateInteval*1000); } };
使用工厂方法
现在还差一个部分,即把所有这些类和对象拼装起来的那个工厂方法.它被实现为一个简单工厂,如下所示.
var FeedManager = { createFeedReader: function(conf){ var displayModule = new ListDisplay(conf.id+'-display',conf.parent); Interface.ensureImplements(displayModule, DisplayModule); var xhrHandler = XhrManager.createXhrHandler(); Interface.ensureImplements(xhrHandler, AjaxHandler); return new FeedReader(displayModule, xhrHandler, conf); } }
使用这个工厂方法,可以把FeedReader类所需的复杂设置封装起来,并且可以确保其成员对象都实现所需接口.
它还把对所使用在特定模块的硬性设定集中在一个位置(ListDisplay和createXhrHandler),哪天要是想使用ParagraphDisplay和QueueHandler,做起来也同样简单,只要改改这个工厂方法内部的代码就行.
等.