聊聊JS與設計模式之(工廠Factory)篇------(麥當勞的故事)

一,整體概要前端

1,筆者淺談express

提及設計模式其實並非什麼很新奇的概念,它也不是基於特定語言所造成的產物,它是基於軟件設計原則以及相關的方法論和通過特定時期衍生出的若干解決方案。本文會以一個實例帶入你們學習設計模式以及與之對應的軟件設計原則來從不一樣角度闡述和分析代碼,而且會給你們提供一些第三方的的實現方式來供參考,還會拿出開源代碼案例來更深刻的理解如何使用設計模式。設計模式

2,直入話題工廠模式是咱們最經常使用的模式了,著名的前端框架Bootstrap以及服務端基於NodeJS的框架(ExpressJS) ,就使用了工廠模式,工廠模式在JS程序中能夠說是隨處可見。爲何工廠模式是如此經常使用?由於工廠模式就至關於建立實例對象的new,咱們常常要根據類生成實例對象,如var button = new Button({}); 工廠模式也是用來建立實例對象的,因此之後當咱們經過new建立對象時就能夠思考一下是否能夠用工廠模式來代替,可能多作一些工做,但會給你係統帶來更大的可擴展性和儘可能少的修改量。前端框架

(1),簡單工廠------簡單工廠的特色就是參數化建立對象,簡單工廠必須知道每一種產品以及什麼時候提供給客戶端。有人會說簡單工廠仍是換湯不換藥,添加新類的時候仍是須要修改這部分的代碼!那麼咱們得到了什麼好處呢?集中變化! 這很好的符合了DRY原則,DRY———Don't Repeat Yourself Principle,直譯爲「不要重複本身」原則^_^ 建立邏輯存放在單一的位置,即便它變化,咱們也只須要修改一處就能夠了。DRY 很簡單,但倒是確保咱們代碼容易維護和複用的關鍵。DRY原則同時還提醒咱們:對系統職能進行良好的分割!職責清晰的界限必定程度上保證了代碼的單一性。這句話對咱們後續的分析極具指導意義,畢竟簡單工廠只是低層次上的代碼複用,如下是一個簡單的例子app

 1 var FullTime = function () {
 2     this.hourly = "$12" ;
 3 };
 4  
 5 var PartTime = function () {
 6     this.hourly = "$11" ;
 7 };
 8  
 9 var Temporary = function () {
10     this.hourly = "$10" ;
11 };
12  
13 var Contractor = function () {
14     this.hourly = "$15" ;
15 };
16 function Factory() {
17     this.createEmployee = function (type) {
18         var employee ;
19         if (type === "fulltime") {
20             employee = new FullTime() ;
21         } else if (type === "parttime") {
22             employee = new PartTime() ;
23         } else if (type === "temporary") {
24             employee = new Temporary() ;
25         } else if (type === "contractor") {
26             employee = new Contractor() ;
27         }
28         employee.type = type ;
29         employee.say = function () {
30             console.log(this.type + ": rate " + this.hourly + "/hour") ;
31         }
32         return employee ;
33     } ;
34 }
35 var factory = new Factory() ;
36 factory.createEmployee("fulltime").say() ;

 

(2),抽象工廠------抽象工廠向客戶端提供了一個接口,使得客戶端在不指定具體產品類型的時候就能夠建立產品中的產品對象。這就是抽象工廠的用意。抽象工廠面的問題是多個等級產品等級結構的系統設計。抽象工廠和工廠方法模式最大的區別就在於後者只是針對一個產品等級結構;而抽象工廠則是面對多個等級結構。一樣出色的完成了把應用程序從特定的實現中解耦,工廠方法使用的方法是繼承,而抽象工廠使用的對象組合。抽象工廠提供的是一個產品家族的抽象類型,這個類型的子類完成了產品的建立。如下是一個簡單的例子框架

 

 1 function Employee(name) {
 2     this.name = name;
 3     this.say = function () {
 4         console.log("I am employee " + name) ;
 5     } ;
 6 }
 7  
 8 function EmployeeFactory() {
 9     this.create = function(name) {
10         return new Employee(name);
11     } ;
12 }
13 function Vendor(name) {
14     this.name = name;
15     this.say = function () {
16         console.log("I am vendor " + name);
17     } ;
18 }
19 function VendorFactory() {
20     this.create = function(name) {
21         return new Vendor(name);
22     } ;
23 }
24 
25 var employeeFactory = new EmployeeFactory() ;
26 employeeFactory.create("BigBear") ;

 

在實際的的使用中,抽閒產品和具體產品之間每每是多層次的產品結構,正如上圖所示學習

 

題外話:簡單工廠的確簡單可是其背後的DRY原則在實踐中讓咱們受益不淺,去年我和個人搭檔作站點的升級工做,寫了不少重複的代碼;代碼重複,源代碼組織混亂,沒有作好規劃和職責分析是原罪。今年新項目,DRY原則是我頭頂的達摩克利斯之劍,不作重複的事情成爲我進行項目計劃組織管理的重要標準。測試

關於工廠模式的階段總結:this

識別變化隔離變化,簡單工廠是一個顯而易見的實現方式url

簡單工廠將建立知識集中在單一位置符合了DRY

客戶端無須瞭解對象的建立過程,某種程度上支持了OCP

添加新的產品會形成建立代碼的修改,這說明簡單工廠模式對OCP支持不夠

簡單工廠類集中了全部的實例建立邏輯很容易違反高內聚的責任分配原則。

 

二,源碼案例參考

1,ExpressJS

見下圖

 

這是esxpress.js文件中建立app的代碼,不難看出這就是一個典型的工廠模式,簡單工廠。

這是application.js文件中的application的初始化代碼。

這樣就很容易看出來 TJ 大神(expressjs的做者)的用意了哈哈哈。好了我再來總結一下:

初始化工做若是是很長一段代碼,說明要作的工做不少,將不少工做裝入一個方法中,至關於將不少雞蛋放在一個籃子裏,是很危險的,這也是有背於面向對象的原則,面向對象的封裝(Encapsulation)和分派(Delegation)告訴咱們,儘可能將長的代碼分派"切割"成每段,將每段再"封裝"起來(減小段和段之間偶合聯繫性),這樣,就會將風險分散,之後若是須要修改,只要更改每段,不會再發生牽一動百的事情,最重要的一句話是將建立與初始化的工做進行分離

三,案例引入------麥當勞的例子

(1),建立麥香雞類

1 function McChicken(){
2     this.getFood = function(){
3         console.log("我來一份麥香雞!") ;
4     } ;
5 } ;

 

(2),建立薯條類

1 function Potato(){
2     this.getFood = function(){
3         console.log("我來一份薯條!") ;
4     } ;
5 } ;

 

(3),建立食物工廠類

function FoodFactory(){    
    return {
        create : function(type){
            var food ;
            if(type === "McChicken"){
                food = new McChicken() ;
            }
            else if(type === "Potato"){
                food = new Potato() ;
            }
            return food ;
        } ;
    } ;
} ;

(4),建立客戶端測試

function MClient(){
    var food = FoodFactory().create("McChicken") ;
    food.getFood() ;
} ;

如今若是我要在吃食物時前洗手如何辦,須要作洗手的工做

修改代碼

function createFood(){
   // doWash(); 洗手工做
    return FoodFactory.create("McChicken") ;
} ;

 

四,總結一下

(1),咱們須要將建立實例的工做與使用實例的工做分開

(2),封裝(Encapsulation)和分派(Delegation)告訴咱們,儘可能將長的代碼分派"切割"成每段,將每段再"封裝"起來(減小段和段之間偶合聯繫性),這樣,就會將風險分散,之後若是須要修改,只要更改每段,不會再發生牽一動百的事情。

 

哈哈哈,本篇結束,未完待續,但願和你們多多交流夠溝通,共同進步(*^__^*) 嘻嘻……

相關文章
相關標籤/搜索