《javascript设计模式》笔记之第七章:工厂模式
在读了这章之后,根据我个人现在的理解,工厂模式就是:将一个类或者一个方法称为一个工厂,然后再将一些模块交给这个工厂,让这个工厂按照给它的不同模块产出不同的实例。
下面为正文:
一:简单工厂:
例子:
分两部分,第一部分:单车厂(负责产出单车)
var BicycleFactory = { createBicycle: function(model) { var bicycle; switch(model) { case 'The Speedster': bicycle = new Speedster(); break; case 'The Lowrider': bicycle = new Lowrider(); break; case 'The Flatlander': bicycle = new Flatlander(); break; case 'The Comfort Cruiser': default: bicycle = new ComfortCruiser(); } Interface.ensureImplements(bicycle, Bicycle); return bicycle; } };
第二部分:单车店,负责买单车
var BicycleShop = function() {}; BicycleShop.prototype = { sellBicycle: function(model) { var bicycle = BicycleFactory.createBicycle(model); bicycle.assemble(); bicycle.wash(); return bicycle; } };
其实很简单,就是讲可分离出来的部分分离出来。
再看一下没有使用简单工厂模式的代码:
var BicycleShop = function() {}; BicycleShop.prototype = { sellBicycle: function(model) { var bicycle; switch(model) { case 'The Speedster': bicycle = new Speedster(); break; case 'The Lowrider': bicycle = new Lowrider(); break; case 'The Comfort Cruiser': default: bicycle = new ComfortCruiser(); } Interface.ensureImplements(bicycle, Bicycle); bicycle.assemble(); bicycle.wash(); return bicycle; } };
很明显,就起到解耦的作用了!
二:工厂模式
真正的工厂模式与简单工厂模式的区别在于,它不是另外使用一个类或对象来创建自行车的,而是使用一个子类。
例子:
先创建一个抽象类,里面的createBicycle方法要子类来实现
var BicycleShop = function() {}; BicycleShop.prototype = { sellBicycle: function(model) { var bicycle = this.createBicycle(model); bicycle.assemble(); bicycle.wash(); return bicycle; }, createBicycle: function(model) { throw new Error('Unsupported operation on an abstract class.'); } };
然后子类实现它的createBicycle方法:
var AcmeBicycleShop = function() {}; extend(AcmeBicycleShop, BicycleShop); AcmeBicycleShop.prototype.createBicycle = function(model) { var bicycle; switch(model) { case 'The Speedster': bicycle = new AcmeSpeedster(); break; case 'The Lowrider': bicycle = new AcmeLowrider(); break; case 'The Flatlander': bicycle = new AcmeFlatlander(); break; case 'The Comfort Cruiser': default: bicycle = new AcmeComfortCruiser(); } Interface.ensureImplements(bicycle, Bicycle); return bicycle; };
另一个子类实现不同的createBicycle方法:
var GeneralProductsBicycleShop = function() {}; extend(GeneralProductsBicycleShop, BicycleShop); GeneralProductsBicycleShop.prototype.createBicycle = function(model) { var bicycle; switch(model) { case 'The Speedster': bicycle = new GeneralProductsSpeedster(); break; case 'The Lowrider': bicycle = new GeneralProductsLowrider(); break; case 'The Flatlander': bicycle = new GeneralProductsFlatlander(); break; case 'The Comfort Cruiser': default: bicycle = new GeneralProductsComfortCruiser(); } Interface.ensureImplements(bicycle, Bicycle); return bicycle; };
三:工厂模式的适用场合
我还不懂,以后多写代码再总结
四:另外一个例子:RSS阅读器
这个例子,有空用来加深理解看看就好了~
/* DisplayModule interface. */ var DisplayModule = new Interface('DisplayModule', ['append', 'remove', 'clear']); /* ListDisplay class. */ var ListDisplay = function(id, parent) { // implements DisplayModule 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 = ''; } }; /* Configuration object. */ var conf = { id: 'cnn-top-stories', feedUrl: 'http://rss.cnn.com/rss/cnn_topstories.rss', updateInterval: 60, // In seconds. parent: $('feed-readers') }; /* FeedReader class. */ 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 + '">' + title.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.updateInterval * 1000); } }; /* FeedManager namespace. */ 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); } };