您好,登錄后才能下訂單哦!
這篇文章主要介紹“JavaScript抽象工廠及工廠方法模式是什么”,在日常操作中,相信很多人在JavaScript抽象工廠及工廠方法模式是什么問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”JavaScript抽象工廠及工廠方法模式是什么”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!
概述
抽象工廠模式廣泛應(yīng)用于因?yàn)樾枨笞儎?dòng)導(dǎo)致一些相似對(duì)象的創(chuàng)建工作,拿我們做項(xiàng)目最熟悉的多版本數(shù)據(jù)庫(kù),根據(jù)數(shù)據(jù)庫(kù)的不同,有可能有SQL Server,Access,Oracle,My SQL版本等等的數(shù)據(jù)庫(kù),這樣我們就能運(yùn)用工廠模式,把各個(gè)數(shù)據(jù)庫(kù)中相似的功能操作封裝到它們各自的對(duì)象模型中,通過工廠對(duì)象統(tǒng)一創(chuàng)建各個(gè)對(duì)象實(shí)例,是客戶程序和這些具體對(duì)象實(shí)現(xiàn)了松耦合;而工廠方法模式主要是針對(duì)某個(gè)對(duì)象的需求變更,但是這個(gè)對(duì)象不會(huì)隨著它的變動(dòng)而導(dǎo)致它所在的業(yè)務(wù)流程中的變動(dòng),它具有高聚合的能力,因此它的外部接口是很穩(wěn)定的;
定義
抽象工廠模式是每個(gè)抽象產(chǎn)品派生多個(gè)具體產(chǎn)品類,每個(gè)抽象工廠派生多個(gè)具體工廠類,每個(gè)具體工廠負(fù)責(zé)多個(gè)(一系列)具體產(chǎn)品的實(shí)例創(chuàng)建。
工廠方法模式是每個(gè)抽象產(chǎn)品派生多個(gè)具體產(chǎn)品類,每個(gè)抽象工廠類派生多個(gè)具體工廠類,每個(gè)具體工廠類負(fù)責(zé)一個(gè)具體產(chǎn)品的實(shí)例創(chuàng)建。
類圖
抽象工廠模式類圖
工廠方法模式類圖
實(shí)例分析
在開始工廠模式之前,有必要先介紹下簡(jiǎn)單工廠的說法,為了避免在客戶程序的對(duì)象出現(xiàn)"if...else..."代碼難以擴(kuò)展以及維護(hù),這里創(chuàng)建一個(gè)工廠類來封裝這些對(duì)象,那這個(gè)就應(yīng)用了簡(jiǎn)單工廠的方式。
這個(gè)場(chǎng)景是這樣,有個(gè)博客網(wǎng)站,在網(wǎng)站中用戶分為幾種類型,我這里暫且暫且分為游客,博客會(huì)員,超級(jí)管理員三種用戶權(quán)限:
◆游客只能進(jìn)行簡(jiǎn)單的查看博客的文章,個(gè)人資料等等;
◆博客會(huì)員還可以對(duì)自己的博客進(jìn)行管理;
◆超級(jí)管理員還可以對(duì)于博客系統(tǒng)后臺(tái)進(jìn)行管理。
在開始介紹之前,先貼出前兩篇介紹的一些接口和類繼承的JS文件InterfaceAndClass.js,這里主要要說的是類繼承的寫法:
function inheritClass(subClass, superClass) { var Func = function() {}; for(p in superClass.prototype) { Func.prototype[p] = superClass.prototype[p]; } subClass.prototype = new Func(); subClass.prototype.constructor = subClass; } |
這里將父類superClass原型的所有方法賦值給新創(chuàng)建的函數(shù)類,之后把函數(shù)類的原型賦值于子類subClass原型中。
一、現(xiàn)在先對(duì)JavaScript簡(jiǎn)單工廠進(jìn)行介紹:
1. 添加用戶類型接口IMember.js:
var IMember = new Interface("IMember", [["getMemberInfo"]]); |
getMemberInfo做為IMember接口的接口方法。
2. 添加三個(gè)具體用戶類型的類Guest.js,BlogMember.js,SuperAdmin.js,繼承IMember接口:
//游客類 function Guest() { Interface.registerImplements(this, IMember); //繼承IMember接口 } Guest.prototype = { getMemberInfo : function() { return "游客"; }, getData : function() { return ""; } } //博客會(huì)員類 function BlogMember() { Interface.registerImplements(this, IMember); } BlogMember.prototype = { getMemberInfo : function() { return "博客會(huì)員"; }, getData : function() { return ""; } } //超級(jí)管理員類 function SuperAdmin() { Interface.registerImplements(this, IMember); } SuperAdmin.prototype = { getMemberInfo : function() { return "超級(jí)管理員"; }, getData : function() { return ""; } }
3. 創(chuàng)建一個(gè)用戶類型工廠類來封裝這些用戶類型的操作,添加MemberFactory.js:
var MemberFactory = { createMemberType : function(memberType) { var _memberType; switch(memberType) { case "guest": _memberType = new Guest(); break; case "blogmember": _memberType = new BlogMember(); break; case "superadmin": _memberType = new SuperAdmin(); break; default: _memberType = new BlogMember(); break; } return _memberType; } } |
通過memberType的“枚舉”,創(chuàng)建相應(yīng)的用戶類型類的對(duì)象;
4. 至此,通過MemberFactory.createMemberType的“靜態(tài)方法”返回一個(gè)用戶類型對(duì)象;
var member = MemberFactory.createMemberType("guest"); //guest, blogmember, superadmin $("#result").html("您當(dāng)前為:" + member.getMemberInfo()); |
(這里$(“…”)寫法是jquery類庫(kù)中的語(yǔ)法,詳細(xì)請(qǐng)看官方文檔http://jquery.com/)
二、接下來開始本篇的重點(diǎn),JavaScript工廠模式的網(wǎng)站應(yīng)用
1. 延續(xù)上面的博客網(wǎng)站的場(chǎng)景:
游客只能進(jìn)行簡(jiǎn)單的查看博客的文章,個(gè)人資料等等;
博客會(huì)員還可以對(duì)自己的博客進(jìn)行管理;
超級(jí)管理員還可以對(duì)于博客系統(tǒng)后臺(tái)進(jìn)行管理;
這里有這些標(biāo)簽Tab:首頁(yè),文章,電影,音樂,相冊(cè),關(guān)于我,文章管理,個(gè)人資料管理,系統(tǒng)后臺(tái)管理,其中 游客只能訪問“首頁(yè),文章,電影,音樂,相冊(cè),關(guān)于我”,博客會(huì)員(登錄后)增加訪問“文章管理,個(gè)人資料管理”,超級(jí)管理員增加訪問“系統(tǒng)后臺(tái)管理”;另外博客會(huì)員和超級(jí)管理員擁有修改皮膚顏色和版塊類型的功能;
最終頁(yè)面顯示如下所示:
從圖上可以看出,博客會(huì)員以上的用戶類型可以顯示“文章管理,個(gè)人資料管理”標(biāo)簽,超級(jí)管理員可以顯示“系統(tǒng)后臺(tái)管理”;而布局選擇包括“左,中,右結(jié)構(gòu)”,“左,右上,右下結(jié)構(gòu)”,“左上,左下,右結(jié)構(gòu)”,顏色包括“藍(lán)”,“紅”,“綠”,“紫”,這里只能博客會(huì)員和超級(jí)管理員才可以顯示;
(這里我使用了網(wǎng)上提供的jquery.tab.js插件對(duì)標(biāo)簽進(jìn)行實(shí)現(xiàn),詳細(xì)請(qǐng)看http://stilbuero.de/jquery/tabs_3/)
好了,現(xiàn)在開始介紹這個(gè)實(shí)例通過JavaScript工廠模式是如何實(shí)現(xiàn)的。
2. IMember.js不變,從簡(jiǎn)單工廠中直接復(fù)制。
3. IMember的具體實(shí)現(xiàn)類Guest,BlogMember,SuperAdmin從簡(jiǎn)單工廠中復(fù)制,這里分別添加個(gè)原型方法isSetColorBlock,判斷該用戶類型是否可設(shè)置顏色和布局,如下所示:
Guest.prototype = { //… isSetColorBlock : function() { return false; } } BlogMember.prototype = { //… isSetColorBlock : function() { return true; } } SuperAdmin.prototype = { //… isSetColorBlock : function() { return true; } } |
可以看到游客不能進(jìn)行設(shè)置,而博客會(huì)員和超級(jí)管理能進(jìn)行設(shè)置;
4. MemberFactory.js不變,從簡(jiǎn)單工廠直接復(fù)制。
5. 添加IBlock.js,創(chuàng)建布局接口:
var IBlock = new Interface("IBlock", [["getData"]]); |
6. 實(shí)現(xiàn)它的具體類,這里添加LMRBlock.js(左 中 右 布局),LRMBlock.js(左上 左下 右 布局),MLRBlock.js(左 右上 右下 布局),這里以LMRBlock.js為例:
// 左、中、右結(jié)構(gòu)樣式版塊 function LMRBlock() { this.color = "blue"; Interface.registerImplements(this, IBlock); //繼承布局IBlock接口 } LMRBlock.prototype = { displayBlock : function() { this.getData(); // 具體布局實(shí)現(xiàn) }, getData : function() { return new Error("抽象方法,不能調(diào)用"); } } |
這里首先創(chuàng)建的是類似于一個(gè)抽象類,該類首先繼承于布局接口,從代碼中可以看出getData方法的實(shí)現(xiàn)返回錯(cuò)誤異常,實(shí)際上它作為一個(gè)抽象方法,不需要實(shí)現(xiàn)任何東西;這里displayBlock方法中調(diào)用它的抽象方法,這里就是典型的抽象方法模式,以備于它的子類繼承實(shí)現(xiàn)它的抽象方法;
現(xiàn)在看看它的子類有哪些:
function BlueLMRBlock(){ } inheritClass(BlueLMRBlock, LMRBlock); //繼承LMRBlock抽象類 BlueLMRBlock.prototype.getData = function() { //父類抽象方法的具體實(shí)現(xiàn) $(".tabs-nav a, .tabs-nav a span").css({"background-image":"url(script/tab/tab_blue.png)"}); this.color = "blue"; } function GreenLMRBlock(){ } inheritClass(GreenLMRBlock, LMRBlock); GreenLMRBlock.prototype.getData = function() { $(".tabs-nav a, .tabs-nav a span").css({"background-image":"url(script/tab/tab_green.png)"}); this.color = "green"; } function RedLMRBlock(){ } inheritClass(RedLMRBlock, LMRBlock); RedLMRBlock.prototype.getData = function() { $(".tabs-nav a, .tabs-nav a span").css({"background-image":"url(script/tab/tab_red.png)"}); this.color = "red"; } function VioletLMRBlock(){ } inheritClass(VioletLMRBlock, LMRBlock); VioletLMRBlock.prototype.getData = function() { $(".tabs-nav a, .tabs-nav a span").css({"background-image":"url(script/tab/tab_violet.png)"}); this.color = "violet"; }
這里包括4種顏色的子類,全部都繼承于抽象類LMRBlock,子類中g(shù)etData的方法做為抽象方法的具體實(shí)現(xiàn);
7. 現(xiàn)在該創(chuàng)建個(gè)工廠來實(shí)現(xiàn)它們了,添加BlockFactory.js文件,首先創(chuàng)建布局抽象工廠類:
function BlockFactory(){ } BlockFactory.prototype = { getBlock : function(block) { var _block; _block = this.createBlock(block); // 添加其他邏輯 // return _block; }, createBlock : function(block) { return new Error("抽象方法,不能調(diào)用"); }, getBlockText : function() { return new Error("抽象方法,不能調(diào)用"); } }; |
這里createBlock和getBlockText同樣是做為抽象方法;
現(xiàn)在要?jiǎng)?chuàng)建三個(gè)繼承于這個(gè)布局抽象工廠類,LMRBlockFactory,LRMBlockFactory,MLRBlockFactory,這里同樣以LMRBlockFactory為例:
function LMRBlockFactory(){ } inheritClass(LMRBlockFactory,BlockFactory); LMRBlockFactory.prototype.createBlock = function(block) { var _block; switch(block) { case "blue": _block = new BlueLMRBlock(); break; case "red": _block = new RedLMRBlock(); break; case "green": _block = new GreenLMRBlock(); break; case "violet": _block = new VioletLMRBlock(); break; default: _block = new BlueLMRBlock(); break; } return _block; }; LMRBlockFactory.prototype.getBlockText = function() { return "LMR"; }; |
LMRBlockFactory繼承于布局抽象工廠類,實(shí)現(xiàn)它的抽象方法createBlock和getBlockText,其中creatBlock通過參數(shù)值,創(chuàng)建對(duì)應(yīng)的布局實(shí)現(xiàn)類,這里用到了典型的抽象工廠模式;
8. 好了,一切都具備好了,現(xiàn)在開始討論我們的前臺(tái)使用了,添加factory.html,引用該引用的JS文件,這里列出一些核心代碼:
1) 添加初始化數(shù)據(jù)
var membertype = "superadmin"; //從用戶類型得到值,這里是個(gè)假設(shè),包含三個(gè)類型用戶: guest,blogmember,superadmin var color = "blue"; //這里是初始化顏色,包括四種顏色:blue,green,red,violet var blockfactory; //布局工廠類的全局變量聲明 |
(你可以通過用戶登錄將登錄信息存入cookies中,從cookies獲取用戶類型和用戶選擇色調(diào))
2) 初始化用戶類型
// 初始化用戶類型 var member = MemberFactory.createMemberType(membertype); $("#spanMemberType").html(member.getMemberInfo()); $("#container-1 li[id^='li']").css("display","block"); $("#container-1 li[id^='li']").each(function(index){ var arr = $(this).attr("power").split('|'); //取得對(duì)應(yīng)標(biāo)簽的權(quán)限數(shù)組 if(arr.indexOf(membertype) == -1) //權(quán)限比較 { $(this).css("display","none"); $("#fragment-" + (index+1)).css("display","none"); } }); if(member.isSetColorBlock()) //是否可設(shè)置布局和顏色 $("#Set").css("display","block"); else $("#Set").css("display","none"); $("#selMemberType").val(membertype); |
通過var member = MemberFactory.createMemberType(membertype);獲取用戶對(duì)象,通過用戶對(duì)象判斷是否可設(shè)置布局和顏色;
3) 初始化版塊類型和顏色類型
// 初始化版塊類型和顏色類型 blockfactory = new LMRBlockFactory(); var block = blockfactory.getBlock(color); block.displayBlock(); $("img[id^='imgcolor_']").removeClass().addClass("color-unselected"); $("#imgcolor_" + color).removeClass().addClass("color-selected"); |
通過創(chuàng)建工廠對(duì)象,從顏色中獲取布局實(shí)現(xiàn)類的對(duì)象,然后通過調(diào)用displayBlock方法的實(shí)現(xiàn)初始化界面的布局;
前臺(tái)JS代碼完整實(shí)現(xiàn)如下:
var membertype = "superadmin"; //從用戶類型得到值,這里是個(gè)假設(shè),包含三個(gè)類型用戶:guest,blogmember,superadmin var color = "blue"; //這里是初始化顏色,包括四種顏色:blue,green,red,violet var blockfactory; //布局工廠類的全局變量聲明 $(function() { $("#container-1").tabs(); // 初始化用戶類型 var member = MemberFactory.createMemberType(membertype); $("#spanMemberType").html(member.getMemberInfo()); $("#container-1 li[id^='li']").css("display","block"); $("#container-1 li[id^='li']").each(function(index){ var arr = $(this).attr("power").split('|'); //取得對(duì)應(yīng)標(biāo)簽的權(quán)限數(shù)組 if(arr.indexOf(membertype) == -1) //權(quán)限比較 { $(this).css("display","none"); $("#fragment-" + (index+1)).css("display","none"); } }); if(member.isSetColorBlock()) //是否可設(shè)置布局和顏色 $("#Set").css("display","block"); else $("#Set").css("display","none"); $("#selMemberType").val(membertype); // 初始化版塊類型和顏色類型 blockfactory = new LMRBlockFactory(); var block = blockfactory.getBlock(color); block.displayBlock(); $("img[id^='imgcolor_']").removeClass().addClass("color-unselected"); $("#imgcolor_" + color).removeClass().addClass("color-selected"); // 用戶類型下拉框綁定 $("#selMemberType").bind("change", function() { $('#container-1').triggerTab(1); var mt = $(this).val(); membertype = MemberFactory.createMemberType(mt); $("#spanMemberType").html(membertype.getMemberInfo()); $("#container-1 li[id^='li']").css("display","block"); $("#container-1 li[id^='li']").each(function(index){ var arr = $(this).attr("power").split('|'); if(arr.indexOf(mt) == -1) { $(this).css("display","none"); $("#fragment-" + (index+1)).css("display","none"); } }); if(membertype.isSetColorBlock()) $("#Set").css("display","block"); else $("#Set").css("display","none"); }); // 版塊類型選擇 $("img[id^='imgblock_']").bind("click", function() { if($(this).className != "block-selected") { $("img[id^='imgblock_']").removeClass().addClass("block-unselected"); $(this).removeClass().addClass("block-selected"); } var blocktext = $(this).attr("id").substring(9); switch(blocktext) { case "LMR": blockfactory = new LMRBlockFactory(); break; case "LRM": blockfactory = new LRMBlockFactory(); break; case "MLR": blockfactory = new MLRBlockFactory(); break; default: blockfactory = new LMRBlockFactory(); break; } var block = blockfactory.getBlock(color); block.displayBlock(); }); // 顏色選擇 $("img[id^='imgcolor_']").bind("click", function() { color = $(this).attr("id").substring(9); var block = blockfactory.getBlock(color); block.displayBlock(); $("img[id^='imgcolor_']").removeClass().addClass("color-unselected"); $("#imgcolor_" + color).removeClass().addClass("color-selected"); }); });
至此,抽象工廠和工廠方法模式的一些思路已經(jīng)應(yīng)用在該博客系統(tǒng)中。
到此,關(guān)于“JavaScript抽象工廠及工廠方法模式是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。