在介紹工廠模式之前,首先我們要理解一下什么是設(shè)計模式?什么是設(shè)計原則?
設(shè)計模式:
通常在我們解決問題的時候,很多時候不是只有一種方式,我們通常有多種方式來解決;但是肯定會有一種通用且高效的解決方案,這種解決方案在軟件開發(fā)中我們稱它為設(shè)計模式;
設(shè)計模式并不是一種固定的公式,而是一種思想,是一種解決問題的思路;恰當?shù)氖褂迷O(shè)計模式,可以實現(xiàn)代碼的復(fù)用和提高可維護性;
設(shè)計原則:
通常在做很多事情的時候,都會有一定的規(guī)范制約;在軟件開發(fā)的過程中,我們可以將設(shè)計原則視為一種開發(fā)規(guī)范,但不是必須要遵循的,只是不遵循的話,代碼后期的維護和復(fù)用都會變得很糟糕;
遵循設(shè)計原則可以幫助我們寫出高內(nèi)聚、低耦合的代碼,當然代碼的復(fù)用性、健壯性、可維護性也會更好;
有哪些設(shè)計模式:
在程序設(shè)計中我們通常認為是有23種設(shè)計模式,根據(jù)分類分別為:
創(chuàng)建型:
1.抽象工廠模式
2.工廠方法模式
3.建造者模式
4.原型模式
5.單例模式(又稱單體模式)
結(jié)構(gòu)型:
1.適配器模式
2.橋接模式
3.組合模式
4.裝飾者模式
5.外觀模式
6.享元模式
7.代理模式
行為型:
1.職責鏈模式
2.命令模式
3.解釋器模式
4.迭代器模式
5.中介者模式
6.備忘錄模式
7.觀察者模式(又稱發(fā)布/訂閱模式)
8.狀態(tài)模式
9.策略模式
10.訪問者模式
11.模板方法模式
有哪些設(shè)計原則:
根據(jù)英文首單詞我們又稱為S.O.L.I.D.設(shè)計原則,一共有5種設(shè)計原則,根據(jù)分類分別為:
1、S(Single responsibility principle)——單一職責原則
一個程序或一個類或一個方法只做好一件事,如果功能過于復(fù)雜,我們就拆分開,每個方法保持獨立,減少耦合度;
2、O(Open Closed Principle)——開放封閉原則
對擴展開放,對修改封閉;增加新需求的時候,我們需要做的是增加新代碼,而非去修改源碼;
例如:我們在使用vue框架的時候,有很多第三方插件我們可以去使用,在使用的時候我們通常都是直接在vue-cli中增加引入代碼,而非去修改vue源碼來達到支持某種功能的目的;
3、L(Liskov Substitution Principle, LSP)——李氏置換原則
子類能覆蓋父類,父類能出現(xiàn)的地方子類就能出現(xiàn);(在JS中沒有類概念,使用較少)
4、I (Interface Segregation Principle)——接口獨立原則
保持接口的單一獨立,類似于單一原則,不過接口獨立原則更注重接口;(在JS中沒有接口概念)
5、D(Dependence Inversion Principle ,DIP)——依賴倒置原則
面向接口編程,依賴于抽象而不依賴于具體,使用方只關(guān)注接口而不需要關(guān)注具體的實現(xiàn);(JS中沒有接口概念)
作為前端開發(fā)人員來說,我們用的最多的設(shè)計原則是S(單一職責原則).O(開放封閉原則),所以在程序設(shè)計的時候我們重點關(guān)注這兩個即可 ;
設(shè)計模式——工廠模式:
所謂工廠模式就是像工廠一樣重復(fù)的產(chǎn)生類似的產(chǎn)品,工廠模式只需要我們傳入正確的參數(shù),就能生產(chǎn)類似的產(chǎn)品;
工廠模式根據(jù)抽象程度依次分為簡單工廠模式、工廠方法模式、抽象工廠模式;
簡單工廠模式:
在我們的生活中很多時候就有這樣的場景,像在網(wǎng)站中有的頁面是需要根據(jù)賬號等級來決定是否有瀏覽權(quán)限的;賬號等級越高可瀏覽的就越多,反之就越少;
// JS設(shè)計模式之簡單工廠
function factory(role){
function superAdmin(){
this.name="超級管理員";
this.viewPage=["首頁","發(fā)現(xiàn)頁","通訊錄","應(yīng)用數(shù)據(jù)","權(quán)限管理"];
}
function admin(){
this.name="管理員";
this.viewPage=["首頁","發(fā)現(xiàn)頁","通訊錄","應(yīng)用數(shù)據(jù)"];
}
function user(){
this.name="普通用戶";
this.viewPage=["首頁","發(fā)現(xiàn)頁","通訊錄"];
}
switch(role){
case "superAdmin":
return new superAdmin();
break;
case "admin":
return new admin();
break;
case "user":
return new user();
break;
}
}
let superAdmin = factory("superAdmin");
console.log(superAdmin);
let admin = factory("admin");
console.log(admin);
let user = factory("user");
console.log(user);
上述代碼中,factory就是一個工廠,factory有三個函數(shù)分別是對應(yīng)不同的產(chǎn)品,switch中有三個選項,這三個選項相當于三個模具,當匹配到其中的模具之后,將會new一個構(gòu)造函數(shù)去執(zhí)行生產(chǎn)工廠中的function;但是我們發(fā)現(xiàn)上面的簡單工廠模式會有一定的局限性,就是如果我們需要去添加新的產(chǎn)品的時候,我們需要去修改兩處位置(需要修改function和switch)才能達到添加新產(chǎn)品的目的;
下面我們將簡單工廠模式進行改良:
// JS設(shè)計模式之簡單工廠改良版
function factory(role){
function user(opt){
this.name = opt.name;
this.viewPage = opt.viewPage;
}
switch(role){
case "superAdmin":
return new user({name:"superAdmin",viewPage:["首頁","發(fā)現(xiàn)頁","通訊錄","應(yīng)用數(shù)據(jù)","權(quán)限管理"]});
break;
case "admin":
return new user({name:"admin",viewPage:["首頁","發(fā)現(xiàn)頁","通訊錄","應(yīng)用數(shù)據(jù)"]});
break;
case "normal":
return new user({name:"normal",viewPage:["首頁","發(fā)現(xiàn)頁","通訊錄"]});
}
}
let superAdmin = factory("superAdmin");
console.log(superAdmin);
let admin = factory("admin");
console.log(admin);
let normal = factory("normal");
console.log(normal);
經(jīng)過上面的修改之后,我們工廠里面的函數(shù)相當于一個萬能摸具,switch里面給我什么,我就加工成什么樣的;自然就解決了添加商品需要修改兩處代碼的問題;
工廠方法模式:
工廠方法模式是將創(chuàng)建對象的工作推到子類中進行;也就是相當于工廠總部不生產(chǎn)產(chǎn)品了,交給下轄分工廠進行生產(chǎn);但是進入工廠之前,需要有個判斷來驗證你要生產(chǎn)的東西是否是屬于我們工廠所生產(chǎn)范圍,如果是,就丟給下轄工廠來進行生產(chǎn),如果不行,那么要么新建工廠生產(chǎn)要么就生產(chǎn)不了;
// JS設(shè)計模式之工廠方法模式
function factory(role){
if(this instanceof factory){
var a = new this[role]();
return a;
}else{
return new factory(role);
}
}
factory.prototype={
"superAdmin":function(){
this.name="超級管理員";
this.viewPage=["首頁","發(fā)現(xiàn)頁","通訊錄","應(yīng)用數(shù)據(jù)","權(quán)限管理"];
},
"admin":function(){
this.name="管理員";
this.viewPage=["首頁","發(fā)現(xiàn)頁","通訊錄","應(yīng)用數(shù)據(jù)"];
},
"user":function(){
this.name="普通用戶";
this.viewPage=["首頁","發(fā)現(xiàn)頁","通訊錄"];
}
}
let superAdmin = factory("superAdmin");
console.log(superAdmin);
let admin = factory("admin");
console.log(admin);
let user = factory("user");
console.log(user);
工廠方法模式關(guān)鍵核心代碼就是工廠里面的判斷this是否屬于工廠,也就是做了分支判斷,這個工廠只做我能生產(chǎn)的產(chǎn)品,如果你的產(chǎn)品我目前做不了,請找其他工廠代加工;
抽象工廠模式:
如果說上面的簡單工廠和工廠方法模式的工作是生產(chǎn)產(chǎn)品,那么抽象工廠模式的工作就是生產(chǎn)工廠的;
舉個例子:代理商找工廠進行合作,但是工廠沒有實際加工能力來進行代加工某產(chǎn)品;無奈又簽署了合同,這時,工廠上面的集團公司就出面了,集團公司承認該工廠是該集團下屬公司,所以集團公司就重新建造一個工廠來進行代加工某商品以達到履行合約;
//JS設(shè)計模式之抽象工廠模式
let agency = function(subType, superType) {
//判斷抽象工廠中是否有該抽象類
if(typeof agency[superType] === 'function') {
function F() {};
//繼承父類屬性和方法
F.prototype = new agency[superType] ();
console.log(F.prototype);
//將子類的constructor指向子類
subType.constructor = subType;
//子類原型繼承父類
subType.prototype = new F();
} else {
throw new Error('抽象類不存在!')
}
}
//鼠標抽象類
agency.mouseShop = function() {
this.type = '鼠標';
}
agency.mouseShop.prototype = {
getName: function(name) {
// return new Error('抽象方法不能調(diào)用');
return this.name;
}
}
//鍵盤抽象類
agency.KeyboardShop = function() {
this.type = '鍵盤';
}
agency.KeyboardShop.prototype = {
getName: function(name) {
// return new Error('抽象方法不能調(diào)用');
return this.name;
}
}
//普通鼠標子類
function mouse(name) {
this.name = name;
this.item = "買我,我線長,玩游戲賊溜"
}
//抽象工廠實現(xiàn)鼠標類的繼承
agency(mouse, 'mouseShop');
//子類中重寫抽象方法
// mouse.prototype.getName = function() {
// return this.name;
// }
//普通鍵盤子類
function Keyboard(name) {
this.name = name;
this.item = "行,你買它吧,沒鍵盤看你咋玩";
}
//抽象工廠實現(xiàn)鍵盤類的繼承
agency(Keyboard, 'KeyboardShop');
//子類中重寫抽象方法
// Keyboard.prototype.getName = function() {
// return this.name;
// }
//實例化鼠標
let mouseA = new mouse('聯(lián)想');
console.log(mouseA.getName(), mouseA.type,mouseA.item); //聯(lián)想 鼠標
//實例化鍵盤
let KeyboardA = new Keyboard('聯(lián)想');
console.log(KeyboardA.getName(), KeyboardA.type,KeyboardA.item); //聯(lián)想 鍵盤
抽象工廠模式一般用于嚴格要求以面向?qū)ο笏枷脒M行開發(fā)的超大型項目中,我們一般常規(guī)的開發(fā)的話一般就是簡單工廠和工廠方法模式會用的比較多一些;
大白話解釋:簡單工廠模式就是你給工廠什么,工廠就給你生產(chǎn)什么;
工廠方法模式就是你找工廠生產(chǎn)產(chǎn)品,工廠是外包給下級分工廠來代加工,需要先評估一下能不能代加工;能做就接,不能做就找其他工廠;
抽象工廠模式就是工廠接了某項產(chǎn)品訂單但是做不了,上級集團公司新建一個工廠來專門代加工某項產(chǎn)品;