1、簡介:
乙個類或物件往往會包含別的物件。在建立這種物件時,你可能習慣於使用常規方法,即用new關鍵字和類建構函式。問題在於這會導致兩個類之間產生依賴性。比如:現在有幾個pc生廠商,生產台式電腦,每個台式電腦的組成部分都是cpu、hardisk、montherboard。生產商從各個硬體商收購硬體,並自行組裝他們賣給顧客,於是我們如下設計這些類:
function cpu()
function hardisk()
function motherboard(){}
function pc(){}
pc.prototype.addcpu = function(cpu)
this.cpu = cpu;
return this;
};pc.prototype.adddisk = function(disk)
this.hardisk = disk;
return this;
};pc.prototype.addmotherboard = function(mboard)
this.motherboard = mboard;
return this;
};/*pc生產商*/
function pcshop(){}
pcshop.prototype.createpc = function();
pcshop的createpc函式所做的工作是生產乙個pc,接著給他組裝上各種硬體,看起來似乎沒啥大問題,假如生廠商業務擴大了,開始做筆記本的生意了,而筆記本雖然也包括cpu、hardisk、motherboard,但是這些硬體和台式電腦的又有區別,適用於筆記本上的硬體繼承於原來的硬體,你怎樣才能較容易的改變createpc以讓它用這些新型別的物件建立pc呢? 這種情況下,改變的最大障礙是createpc對被例項化的類進行了硬編碼,也許你可以在函式中增加引數,並增加一些**組裝筆記本。如果某天,廠商又要生產平板電腦了呢? 這種不靈活意味著我們應該重新設計,通過以下工廠模式可以弱化物件之間的耦合。
2、抽象工廠(abstrack factory)
抽象工程提供乙個建立一系列相關或相互依賴物件的介面,而無需指定它們具體的類。我們把上述**中的「建立新例項」這部分工作分離出來,轉交給工廠物件,上述情景可以抽象出乙個基本的工廠物件,這個基本的工廠物件提供生產產品的介面,更具體的工廠繼承這個基本工廠,根據需要實現更具體的介面。乙個應用中一般每個產品系列只需乙個具體的工廠,因此工廠通常最好實現為乙個單例。於是我們首先增加乙個基本工廠的單例,在很多情況下,這個基本工廠都實現為抽象類,即只是提供公共介面,不過特定於我們的環境下,實現為提供預設的產品:
******修改和增加的********/
/*pc工廠*/
var pcfactory = ,
makehardisk:function(),
makemotherboard:function()
};/*pc生產商*/
function pcshop(){}
pcshop.prototype.createpc = function(factory);
上述**新增加了乙個pcfactroy物件,提供了生產基本產品的介面,在createpc函式中,增加了乙個工廠引數,用於獲得各種產品,這裡並未檢查引數的型別,實際應用中,應該配合介面一起工作。我們現在來看看,加入廠商增加筆記本產品的實現,我們說過,乙個例項化的工廠對應乙個產品系列,於是我們增加乙個筆記本工廠,同時根據筆記本硬體和台式電腦的差距,新增加適合於筆記本的硬體產品類。設計如下:
/******修改和增加的********/
function notecpu()
notecpu.extend(cpu); //用到了以前我們增加的extend函式
/*筆記本工廠單例,內部繼承pc工廠,*/
var notebookfactory = function();
f.prototype.makecpu = function();
f.extend(pcfactory);
var obj = new f();
return obj;
}();
上述**新增了乙個notecpu類,繼承於cpu類,這裡簡單起見,沒有增加其他新的硬體類,筆記本工廠單例物件通過自執行函式在內部建立建構函式,實現了單例的繼承,當然也可以直接定義notebookfactroy為字面量物件,自己擴充套件乙個函式將pcfactory中的未改變的介面賦給notebookfactory。我們無需改動createpc,就可以任意的增加新的產品系列,生產台式電腦這樣呼叫: var shop = new pcshop(); pc.createpc(pcfactroy); 生產筆記本則可以這樣呼叫:pc.createpc(notebookfactory);
3、工廠方法(factroy method)
工廠方法定義了乙個用於建立物件的介面,讓子類決定例項化哪乙個類,它使乙個類的例項化延遲到子類。 從示例角度看, pc廠商增加了筆記本業務,可以看成新開了一家筆記本店,即notebookshop, 台式電腦店面按著自己的流程組裝機器(createpc),同樣是獲得cpu(makecpu),獲得hardisk(makehardisk),獲得motherboard(makemotherboard), 筆記本店面的組裝流程與台式電腦是一樣的,唯一不同的是獲得的硬體型別稍有差異,也許哪天擴充套件了平板電腦的業務,但流程還是一致的,區別的只是硬體獲得的型別,於是我們可以把pcshop作為基類,具有一組基本的製作硬體的介面,而其他型別的pc從這繼承而來,實現自己的介面。設計如下:
/******修改和增加的********/
/*pc工廠,這裡預設生產基本的台式電腦*/
var pcshop = ,
makehardisk:function(),
makemotherboard:function(),
createpc:function()
};/*筆記本工廠單例,內部繼承pcshop*/
var notebookshop = function();
f.prototype.makecpu = function();
f.extend(pcshop);
var obj = new f();
return obj;
}();
上述**中,pcshop為最基本的pc工廠,預設生產最基本的台式電腦,提供了乙個公共的產生物件的介面createpc, 並提供了基本的硬體獲得方法,notebookshop繼承了pcshop,並實現了自己的cpu獲得途徑以適應筆記本,若哪天增加平板業務,我們也只需要增加乙個padshop類,並根據需要實現對應的介面。 《JavaScirpt設計模式》(6) 工廠模式
1 簡介 乙個類或物件往往會包含別的物件。在建立這種物件時,你可能習慣於使用常規方法,即用new關鍵字和類建構函式。問題在於這會導致兩個類之間產生依賴性。比如 現在有幾個pc生廠商,生產台式電腦,每個台式電腦的組成部分都是cpu hardisk montherboard。生產商從各個硬體商收購硬體,...
設計模式6
template method模式 我們講的前面很多模式的思路都是使用組合,而不用繼承。並且也提到了乙個設計原則 優先使用組合 但是這個模式就是乙個使用繼承來解決問題的思路。畢竟,繼承也不是一無是處。在有些系統中,乙個事務的完成需要通過一系列的步驟,就是第一步幹什麼,第二步幹什麼。這個步驟的序列是固...
設計模式 6 裝飾模式
裝飾是一種概念設計模式,允許你通過將物件放入特殊封裝物件中來為原物件增加新的行為 public inte ce datasource介面預設實現類 public class filedatasource implements datasource override public void write...