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,做起来也同样简单,只要改改这个工厂方法内部的代码就行.

等.

posted @ 2014-03-30 19:36  JChen___  阅读(301)  评论(0编辑  收藏  举报