聽飛狐聊JavaScript設計模式系列07

本回內容介紹

上一回聊到JS單例模式(singleton),作了一道題,內容很少,比較容易理解。
介一回嘞,聊聊工廠模式,以前聊到過工廠模式,這回聊深刻點兒,可能會比較抽象,不過好在實際開發中使用還算普遍,理解起來會比較容易,開始咯:javascript

1. 簡單工廠

好比咱們建立一個會員系統,有會員和管理員兩種角色,每種角色有登陸,註銷的功能,
這裏須要引入以前講過的接口類,以下:java

// 用戶類
function User(){};

// 用戶工廠模式
User.prototype = {
    // 還原構造器,指向User
    constructor:User,
    // 建立用戶的方法,傳入的type是用戶類型
    createUser:function(type){
        // 這裏建一個變量,用於返回實例
        var user;
        // 判斷傳入的用戶類型,返回該類型的實例
        switch(type){
            case 'Member':user = new Member();break;
            case 'Admin' :user = new Admin();break;
        };
        // 這裏以前講過的,檢測接口
        Interface.ensureImplements(user,UserInterface)
        return user;
    }
}

// 建立一個用戶接口,並且必須實現該接口的login,logout兩個方法
var UserInterface = new Interface('UserInterface',['login','logout']);

// 會員類,包括實現的接口方法
function Member(){}
Member.prototype.login = function(){alert('會員登陸');}
Member.prototype.logout = function(){alert('會員註銷');}

// 管理員類,包括實現的接口方法
function Admin(){}
Admin.prototype.login = function(){alert('管理員登陸');}
Admin.prototype.logout = function(){alert('管理員註銷');}

// new一個用戶工廠
var o = new User();
// 建立一個管理員
var a = o.createUser("Admin");
// 調用login方法
a.login();

// 下面一堆是會員的實現,不用多說了吧
var o2 = new User();
var m = o.createUser("Member");
m.logout();

這就是一個簡單工廠模式實現了,應該不少盆友已經看出來了,一樣的方法要實現兩次,好像有點冗餘了吧,那麼就能夠用到以前的繼承了,改吧改吧,帥狐show time:設計模式

2. 簡單工廠之解耦

這裏要用到以前寫的繼承類了,寫一個用戶基類,還要考慮到每一個用戶和管理員分別有不一樣的權限,那麼咱們能夠再作一次工廠解耦,細化粒度,以下:數組

function User(){};

User.prototype = {
    constructor:User,
    // 給用戶配置權限,type是用戶類型
    assignRole:function(type){
        // 建立用戶,這裏還能夠作不少擴展,這裏先留...
        var user = UserFactory.createUser(type);
        return user;
    }
}

// 建立用戶的工廠(還記的上一回的單例模式嗎,這也是個單例模式喲)
var UserFactory = {
    // 這裏爲了解耦,跟上面的代碼對比一下,換了個位置
    createUser:function(type){
        var user;
        switch(type){
            case 'Member':user = new Member();break;
            case 'Admin' :user = new Admin();break;
        };
        Interface.ensureImplements(user,UserInterface)
        return user;
    }
}

var UserInterface = new Interface('UserInterface',['login','logout']);
// User的基類,若是有疑惑,看看以前講的繼承
function BaseUser(){};
BaseUser.prototype = {
    constructor:BaseUser,
    login:function(){
        alert(this.constructor.name + ' 登陸');
    },
    logout:function(){
        alert(this.constructor.name + ' 註銷');
    }
}
// 用戶類,繼承基類,這樣就有了兩個方法
function Member(){}
extend(Member,BaseUser);

// 管理員類,這樣就避免了重複建立的冗餘
function Admin(){}
extend(Admin,BaseUser);

// 這裏沒什麼好說的,實例測試
var o = new User();
var a = o.assignRole("Admin");
a.login();

var o2 = new User();
var m = o.assignRole("Member");
m.logout();

這個例子稍微開始有點複雜了,結合了以前聊的接口,繼承,單例等,在配置權限的地方其實還能夠作不少擴展,好比:
有會員有不一樣等級的會員,管理有不一樣等級的管理員,不一樣的級別存在不一樣的方法,要作到這樣的話,咱們能夠經過抽象類,讓每一個類覆蓋方法,動態的建立工廠,來吧,繼續帥狐show time:ide

3. 簡單工廠之抽象類

不一樣的用戶組有不一樣的角色,不一樣的角色擁有不一樣的權限,以下:測試

function User(){};
User.prototype = {
    constructor:User,
    // 這裏是個抽象方法,每一個類能夠根據不一樣的需求來重載
    assignRole:function(type){
        // 調用自身的抽象方法,意義是在無重載的時候執行
        this.abs(type);
    },
    // 這裏是在無重載的時候執行
    abs:function(){
        throw new Error('the abstract class can override the virtual method with an abstract method.');
    }
};

// 單獨定義Member組
function MemberGroup(){}
extend(MemberGroup,User);
MemberGroup.prototype = {
    constructor:MemberGroup,
    // 分配權限方法,根據傳入的角色來建立不一樣的實例
    assignRole:function(type){
        var role;
        // 這裏定義兩個角色,會員和高級會員
        var group = ['Member','SeniorMember'];
        // indexOf眼熟吧,第一回的時候聊過的ES5的新玩意
        if(group.indexOf(type)>-1){
            // 調用用戶工廠的建立用戶方法
            role = UserFactory.createUser(type);
        }else{
            alert('無該'+type+'角色!');
        }
        return role;
    }
}

// 跟上面同樣,這裏定義Admin
function AdminGroup(){}
extend(AdminGroup,User);
AdminGroup.prototype = {
    constructor:AdminGroup,
    assignRole:function(type){
        var role;
        // 這裏定義兩個角色,管理員和高級管理員
        var group = ['Admin','SeniorAdmin'];
        if(group.indexOf(type)>-1){
            role = UserFactory.createUser(type);
        }else{
            alert('無該'+type+'角色!');
        }
        return role;
    }
}

// 建立用戶的工廠(跟上一個例子同樣,只是這裏是動態建立工廠)
var UserFactory = {
    createUser:function(type){
        // eval()直接執行
        var user = eval('new '+type+'()');
        Interface.ensureImplements(user,UserInterface)
        return user;
    }
}

var UserInterface = new Interface('UserInterface',['login','logout']);
// User的基類,若是有疑惑,看看以前講的繼承
function BaseUser(){};
BaseUser.prototype = {
    constructor:BaseUser,
    login:function(){
        alert(this.constructor.name + ' 登陸');
    },
    logout:function(){
        alert(this.constructor.name + ' 註銷');
    }
}
// 會員類,繼承基類,這樣就有了兩個方法
function Member(){}
extend(Member,BaseUser);

// 高級會員類,有本身特有的高級方法
function SeniorMember(){}
extend(SeniorMember,BaseUser);
SeniorMember.prototype.seniorM = function(){alert('高級會員的權限')};

// 管理員類,這樣就避免了重複建立的冗餘
function Admin(){}
extend(Admin,BaseUser);

// 高級管理員類,有本身特有的高級方法
function SeniorAdmin(){}
extend(SeniorAdmin,BaseUser);
SeniorAdmin.prototype.seniorA = function(){alert('高級管理員的權限')};

// 這裏其實能夠回憶一下裝飾者模式,把高級管理員的實例作一次包裝
var obj = new SeniorAdmin();
// 超級管理員類,裝飾高級管理員的實例
function SuperAdmin(obj){}
SuperAdmin.prototype.superA = function(){
    obj.seniorA();
    alert('再彈一個窗,特效,特效,加特效!由於我是超級管理員!喲呼~~');
};

// 這裏沒什麼好說的,實例測試
var o = new MemberGroup();
var a = o.assignRole("SeniorMember");
a.seniorM();

var o2 = new AdminGroup();
var m = o2.assignRole("SeniorAdmin");
m.seniorA();

var o3 = new SuperAdmin(obj);
o3.superA();

這個例子有點略複雜,在上一個例子的基礎上作了抽象類,還複習了裝飾者模式,若是感受暈菜,能夠跳過。
這裏其實還能夠進一步優化,達到高聚類低耦合,這裏工廠模式就告一段落了。優化

裝逼圖
裝個逼先。今天看優酷放出了新版嘻哈四重奏,一看沒有了原版人馬,就算是笑點也笑不起來了,算了換一個劇看,啊呃~~ui

這一回聊的內容比較繞腦殼,反正感受暈菜的話就啓動囫圇吞棗模式,想不通的先停下,之後再回過來看或許就恍然大悟,
下面的內容,跟上一回同樣,就一道題好了。this

題目:快速排序

這個快速排序比較基礎,網上不少,這裏我就把註釋寫清楚一點,方便你們理解:spa

var arr = [12,5,36,6,22,66];
// 快速排序
function quickSort(arr){
    // 判斷數組長度,只有小等於1的時候返回
    if(arr.length<=1){
        return arr;
    }
    // 向下取整,也就是取一半的長度
    var num = Math.floor(arr.length/2);
    // 取中間的那個數
    var numValue = arr.splice(num,1);
    // 定義兩個數組作容器
    var left = [];
    var right = [];
    // 循環數組
    for(var i=0;i<arr.length;i++){
        // 當小於中間數的時候,放到left數組,大於中間數則放到right數組
        if(arr[i]<numValue){
            left.push(arr[i]);
        }else{
            right.push(arr[i]);
        }
    }
    // 遞歸調用,再將left數組,中間數還有right數組合併成一個新數組,而後返回這個新數組
    return quickSort(left).concat([numValue],quickSort(right));
};
alert(quickSort(arr));  // 5,6,12,22,36,66

網上找的例子,註釋寫的還算清楚吧,難度不大,跟上一回同樣,當娛樂消遣。

這一回,主要聊了工廠模式,而且將前面的內容融合了進去,複習了繼承,接口,單例模式,裝飾者模式,涉及了一些簡單的業務邏輯,對於剛接觸面向對象,設計模式的童鞋稍微有點難度~~
下一回,就聊用的比較頻繁的一個設計模式,門面模式。

客觀看完點個贊,推薦推薦唄,嘿嘿~~


注:此係飛狐原創,轉載請註明出處

相關文章
相關標籤/搜索