設計模式——工廠模式

weixin_33763244發表於2016-08-22

簡單工廠模式(建立單一的物件)

示例1

描述

工廠模式主要是為了建立物件例項或者類簇(抽象工廠), 關心的是最終產出(建立)的物件, 而不關心建立的過程.

在出現多個類的時候, 每次建立需要找到對應的類往往比較麻煩, 這時候通常使用一個函式進行封裝來建立所需要的物件,
這樣就無需關注建立這些物件到底依賴哪些基類了, 只要知道有這個函式就可以了, 通常這個函式被稱為工廠函式,
這種模式叫簡單工廠模式

案例

假設一體育商品店賣器材, 裡面有很多體育商品, 及其相關介紹. 當你來到體育用品店買一個籃球及相關介紹時,
你只需要問售貨員, 她會幫你找到你所需要的東西.

實現

// 籃球基類
var Basketball = function() {
    this.intro = '籃球盛行於美國';
}
Basketball.prototype = function() {
    getMember: function() {
        console.log('每個隊伍需要5名隊員');
    },
    getBallSize: function() {
        console.log('籃球很大');
    }
}

// 足球基類
var Football = function() {
    this.intro = '足球在世界範圍內盛行';
}
Football.prototype = function() {
    getMember: function() {
        console.log('每個隊伍需要11名隊員');
    },
    getBallSize: function() {
        console.log('足球很大');
    }
}

// 網球基類
var Tennis = function() {
    this.intro = '每年有很多網球系列賽';
}
Tennis.prototype = function() {
    getMember: function() {
        console.log('每個隊伍需要1名隊員');
    },
    getBallSize: function() {
        console.log('網球很小');
    }
}

// 運動工廠(這邊相當於諮詢體育器材店的售貨員, 告訴她你想要買什麼體育用品)
var SportFactory = function(name) {
    switch(name) {
        case 'basketball':
            return new Basketball();
        case 'football':
            return new Football();
        case 'tennis':
            return new Tennis();
    }
}

var ball = new SportFactory('tennis');
console.log(ball.intro)            // 每年有很多網球系列賽
console.log(ball.getMember());    // 每個隊伍需要1名隊員

示例2

描述

簡單工廠模式的理念就是建立物件, 而除此之外, 簡單工廠模式還可以建立相似物件. 在建立多個類的時候, 假設每個類都有很多相似的地方, 比如在多種彈出框上都有關閉按鈕, 都有提示文案等. 可以通過將這些相似的東西提取, 不相似針對性處理即可.

案例

假設當前專案需求是需要做各種彈出框: 警示框, 確認框及提示框.

實現

var LoginAlert = function(text) {
    this.content = text;
};
LoginAlert.prototype.show = function() {
    // 顯示警示框
};

var LoginConfirm = function(text) {
    this.content = text;
};
LoginConfirm.prototype.show = function() {
    // 顯示確認框
};

var LoginPrompt = function(text) {
    this.content = text;
};
LoginPrompt.prototype.show = function() {
    // 顯示提示框
};

function createPop(type, text) {
    var o = new Object();
    o.content = text;
    o.show = function() {
        // 顯示方法
    };
    if(type === 'alert') {
        // 警示框差異部分
    }
    if(type === 'confirm') {
        // 確認框差異部分
    }
    if(type === 'prompt') {
        // 提示框差異部分
    }

    return o;
}

// 建立警示框
var userNameAlert = createPop('alert', '使用者名稱只能是26個字母和數字');

工廠方法模式(建立多類物件)

示例

描述

通過對產品類的抽象使其建立業務主要負責用於建立多類產品的例項.

案例

假設有一批關於計算機培訓的廣告資源需要投放, 一批是PHP要求黃色字型紅色背景, 一批JAVA綠色字型,
一批JAVASCRIPT粉色背景....

實現

var Java = function(content) {
    this.content = content;
    (functiont(content) {
        var div = document.createElement('div');
        div.innerHTML = content;
        div.style.color = 'green';
        document.getElementById('container').appendChild(div);
    })(content);
};

var Php = function(content) {
    this.content = content;
    (functiont(content) {
        var div = document.createElement('div');
        div.innerHTML = content;
        div.style.color = 'yellow';
        div.style.background = 'red';
        document.getElementById('container').appendChild(div);
    })(content);
};

var Javascript = function(content) {
    this.content = content;
    (functiont(content) {
        var div = document.createElement('div');
        div.innerHTML = content;
        div.style.background = 'pink';
        document.getElementById('container').appendChild(div);
    })(content);
};

// 建立學科類工廠
function JobFactory(type, content) {
    switch(type) {
        case 'java':
            return new Java(content);
        case 'php':
            return new Php(content);
        case 'Javascript':
            return new Javascript(contet);
    }
}

// 又要添需求啦.....多加一批UI學科, 紅色邊框.....

// 程式碼改進:

var Factory = function(type, content) {
    if(this instanceof Factory) {
        var s = new this[type] (content);
        return s;
    } else {
        return new Factory(type, content);
    }
};

// 在工廠原型中設定建立所有型別資料物件的基類
Factory.prototype = {
    Java: function() {
        // ...
    },
    Php: function() {
        // ...
    },
    Javascript: function() {
        // ...
    },
    UI: function() {
        // ...
    }
};

var data = [
    {type:'JavaScript', content:'javascript'},
    {type:'Java', content:'java'},
    {type:'PHP', content:'php'},
    {type:'UI', content:'ui'}
];

for(var i = data.length; i >= 0; i--) {
    Factory(data[i].type, data[i].content);
}

抽象工廠模式(建立類簇)

示例

描述

抽象工廠模式一般不用來建立具體物件, 抽象類中定義的方法只是顯性地定義一些功能, 但沒有具體的實現, 而一個物件需要具有一套完整的功能, 所以用抽象類建立的物件也是抽象的而非真實物件. 因此一般用它作為父類來建立子類.

抽象工廠其實是一個實現子類繼承父類的方法, 在這個方法中需要通過傳遞子類以及要繼承父類(抽象類)的名稱,並且在抽象工廠方法中又增加了一次對抽象存在性的一次判斷, 如果存在, 則將子類繼承父類的方法. 然後子類通過寄生式繼承.繼承父類的原型中需要注意一點是, 在對過渡類的原型繼承時, 不是繼承父類的原型, 而是通過new關鍵字複製父類的一個例項, 這麼做事因為過渡類不應僅僅繼承父類的原型方法, 還要繼承父類的物件屬性, 所以要通過new關鍵字將父類的建構函式執行一遍來複制建構函式中的屬性和方法

抽象工廠新增抽象類比較特殊, 因為抽象工廠是個方法不需要例項化物件, 故只需要一份, 因此直接為抽象工廠新增類的屬性即可.

實現

// 抽象工廠方法
var VehicleFatory = function(subType, superType) {
    // 判斷抽象工廠中是否有該抽象類
    if(typeof VehicleFactory[superType] === 'function') {
        // 快取類
        function F() {};
        // 繼承父類屬性和方法
        F.prototype = new VehicleFactory[superType] ();
        // 將子類constructor 指向子類
        subType.constructor = subType;
        // 子類原型繼承'父類'
        subType.prototype = new F();
    } else {
        // 不存在該抽象類丟擲錯誤
        throw new Error('未建立該抽象類');
    }
};

// 小汽車抽象類
VehicleFactory.Car = function() {
    this.type = 'car';
};
VehicleFactory.Car.prototype = {
    getPrice: function() { return new Error('抽象方法不能呼叫'); },
    getSpeed: function() { return new Error('抽象方法不能呼叫'); }
};

// 公交車抽象類
VehicleFactory.Bus = function() {
    this.type = 'bus';
};
VehicleFactory.Bus.prototype = {
    getPrice: function() { return new Error('抽象方法不能呼叫'); },
    getSpeed: function() { return new Error('抽象方法不能呼叫'); }
};

// 貨車抽象類
VehicleFactory.Truck = function() {
    this.type = 'truck';
};
VehicleFactory.Truck.prototype = {
    getPrice: function() { return new Error('抽象方法不能呼叫'); },
    getSpeed: function() { return new Error('抽象方法不能呼叫'); }
};

// 建立產品子類繼承相應的產品簇抽象類
// 寶馬汽車子類
var BMW = function(price, speed) {
    this.price = price;
    this.speed = speed;
}
//抽象工廠實現對Car抽象類的繼承
VehicleFactory(BMW, 'Car');
BMW.prototype.getPrice = function() { return this.price };
BMW.prototype.getSpeed = function() { return this.speed };

// 公交車...
// 貨車...

相關文章