1. 程式人生 > >JavaScript設計模式第一彈-建立型設計模式

JavaScript設計模式第一彈-建立型設計模式

前言

接下來將會為大家介紹設計模式中的建立型設計模式,在此之前需要掌握一定的JavaScript物件繼承基礎。

簡單工廠模式

先說說

  • 什麼是簡單工廠模式:又叫靜態工廠方法,由一個工廠物件決定建立某一種產品物件類的例項

看著定義有點懵,沒關係。繼續往下走

工廠函式

  • 說明:簡單來說,就是為了把多個相同型別的類整合到一個函式內,我們把這個函式叫做工廠函式
  • 用途:使得其他人不用關注建立物件是基於哪個基類,直接用該工廠函式即可
  • 程式碼
//定義小貓類
var Cat = function(){
    this.voice = '喵';
}
Cat.prototype.getVoice = function(){
    console.log(this.voice);
}

//定義小狗類
var Dog = function(){
    this.voice = '汪';
}
Dog.prototype.getVoice = function(){
    console.log(this.voice);
}

//動物工廠
var AnimalFactory = function(name) {
    switch(name){
        case 'cat':
            return new Cat();
        case 'dog':
            return new Dog();
    }
}

//建立例項
var hellokity = AnimalFactory('cat');
hellokity.getVoice();   //'喵'

當然,上面兩種方法十分相似,於是還可以有下面的定義方式:

var createAnimal = function(name,voice) {
    var o = new Object(); 
    o.name = name;
    o.voice = voice;
    o.getVoice = function() {
        console.log(this.voice);
    }
    return o;
}
var hellokity = createAnimal('hellokity','喵');
hellokity.getVoice();   //'喵'

看似最後一種方法好像簡便不少,但是實際上這兩種定義方法是有區別的。

  • 第一種方式所定義的例項物件是擁有父類的方法,也就是可以訪問到原型鏈上面的屬性和方法的。
  • 第二種方式定義則是因為在內部新建了一個物件,那麼父級物件什麼的自然也就不存在了(當然這裡不是指object)。

最後回顧

最後再次加深對簡單工廠模式的印象吧

簡單工廠模式:又叫靜態工廠方法,由一個工廠物件決定建立某一種產品物件類的例項

工廠方法模式

先說說

  • 什麼是工廠方法模式:通過對產品類的抽象使其建立業務主要負責用於建立多類產品的例項

懵?沒關係。繼續往下走

安全模式類

  • 用途:可以遮蔽使用該類的所造成的錯誤
  • 例子
var Demo = function() {};
Demo.prototype.getName = function(){
    console.log('get success!')
}

var d = Demo();
d.getName();    //報錯

//安全模式類
var Demo = function() {
    if(!(this instanceof Demo)){
        return new Demo
    }
};
Demo.prototype.getName = function(){
    console.log('get success!')
}

var d = Demo();
d.getName();    //'get success!'

工廠方法

實際上工廠方法和簡單工廠模式區別在於:簡單工廠模式如果需要增加類的話,那麼它則需要改變兩處地方,一處是工廠函式,一處是改變類。但是如果是工廠方法模式的話,則只需要往工廠方法中新增基類則可以。程式碼實現如下:

//安全模式建立的工廠類
var superHeroFatory = function(type,skill){
    if(this instanceof superHeroFatory){
        var s = new this[type](skill);
        return s
    }else{
        return new superHeroFatory(type,skill)
    }
}
superHeroFatory.prototype = {
    IronMan: function(skill){
        this.name = 'Iron Man';
        this.skill = skill;
        this.getName = function(){
            console.log(this.name);
        }
        this.getSkill = function(){
            console.log(this.skill);
        }
    },
    CaptainAmerica: function(skill){
        this.name = 'Captain America';
        this.skill = skill;
        this.getName = function(){
            console.log(this.name);
        }
        this.getSkill = function(){
            console.log(this.skill);
        }
    }
}

var captainAmerica = superHeroFatory('CaptainAmerica','shield');
captainAmerica.getName();   //'Captain America'
captainAmerica.getSkill();  //'shield'

最後回顧

這個工廠方法模式解決了建立多類物件所帶來的麻煩,這樣的工廠方法物件的方式也避免了使用者與物件類之間的耦合,使用者不關心建立該物件的具體類,只需呼叫工廠方法即可。

抽象工廠模式

先說說

  • 什麼是抽象工廠模式:通過對類的工廠抽象使其業務用於對產品類簇的建立,而不負責建立其某一類產品的例項

看著定義有點懵,沒關係。繼續往下走

抽象類

  • 概念:抽象類是一種宣告但不能使用的類,使用就會報錯。
  • 用途:定義一個產品簇,並宣告一些必備的方法,如果子類沒有重寫就會報錯
  • 例子:在java中可以簡單定義,但是在js中的話暫時還沒有這種抽象類的定義,於是我們可以用這種方式模仿抽象類:
var Car = function() {};
Car.prototype = {
    getPrice(){
        return new Error('抽象方法不可用')
    },
    getName(){
        return new Error('抽象方法不可用')
    }
}

於是乎,在物件例項化後呼叫這些函式就會報錯。因為抽象類是沒有具體實現的,它只用作繼承的方式

抽象工廠模式

  • 說明:為了更好的建立抽象類,於是將抽象類整合為一個抽象工廠
  • 用途:用於建立抽象物件的一種方法
  • 定義
var VehicleFactory = 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(){
        return new Error('抽象方法不可用')
    },
    getName(){
        return new Error('抽象方法不可用')
    }
}

//大巴抽象類
VehicleFactory.Bus = function(){
    this.type = 'bus';
}
VehicleFactory.Bus.prototype = {
    getPrice(){
        return new Error('抽象方法不可用')
    },
    getName(){
        return new Error('抽象方法不可用')
    }
}

抽象類的實現

啥也別說了,直接上碼

var BMW = function(price,name){
    this.price = price;
    this.name = name;
}
VehicleFactory(BMW,'Car');
BMW.prototype.getName = function(){
    console.log(this.name);
}

var X2 = new BMW(200,'X2');
X2.getName();   //'X2'
X2.getPrice();  //報錯,因為忘記定義這個方法了

最後回顧

最後再次感受一下定義吧

抽象工廠模式:通過對類的工廠抽象使其業務用於對產品類簇的建立,而不負責建立其某一類產品的例項

建造者模式

先說說

  • 什麼是建造者模式:將一個複雜物件的構建層與其表示層相互分離,同樣的構建過程可採用不同的表示

與工廠模式差別

  • 工廠模式主要是為了建立物件例項或者類簇(抽象工廠),關心的是最終建立的是什麼,而對建立的過程並不關心
  • 建造者模式在建立物件時要更復雜,它更多的關心建立物件的過程甚至於每個細節。或者說這種模式建立了一個複合物件

建造者模式

  • 說明:關心建立物件的過程,對於建立的具體實現的細節也參與了干涉
  • 用途:當需要我們建立物件不僅需要得到物件例項,還需對物件細化時,則可以使用建造者模式
  • 程式碼
//建立類
var Human = function(props){
    this.name = props && props.name || '保密';
}
Human.prototype.getName = function(){
    console.log(this.name);
}

//名字類
var Name = function(name){
    var that = this;
    (function(name,that){
        that.wholeName = name;
        if(name.indexOf(' ') > -1){
            that.FirstName = name.slice(0,name.indexOf(' '));
            that.SecondName = name.slice(name.indexOf(' '));
        }
    })(name,that)
}


var Person = function(name){
    var _name = new Name(name);
    var _person = new Human({name:_name});
    return _person
}

var Miles = new Person('Miles Jiang');
Milse.getName();    //{wholeName: "Miles Jiang", FirstName: "Miles", SecondName: " Jiang"}

最後回顧

這種模式下,我們就可以關心到物件的建立過程。因此我們通常將建立物件模組化,這樣使得被建立的類的每個模組都可以獲得靈活的運用和高質量的複用

單例模式

先說說

  • 什麼是單例模式:又被稱為單體模式,是隻允許例項化一次的物件類。有時我們也用一個物件來規劃一個名稱空間,井井有條地管理物件上的屬性與方法

名稱空間

  • 說明:用來約束每個人定義的變數
  • 用途:防止共同開發時帶來的變數名衝突
  • 例子
var Miles = {
    getDom: function(id){
        return document.getElementById(id)
    }
}

最後回顧

為了梳理程式碼,使得程式碼有序整潔

後話

本文章是通過學習張榮銘所著的《JavaScript設計模式》所總結。希望大家看完文章可以學到東西,同時也推薦大家去看看這本設計模式,寫得很不錯。

成功不在一朝一夕,我們都需要努力