资讯专栏INFORMATION COLUMN

听飞狐聊JavaScript设计模式系列07

BetaRabbit / 217人阅读

摘要:本回内容介绍上一回聊到单例模式,做了一道题,内容不多,比较容易理解。这里其实还可以进一步优化,达到高聚类低耦合,这里工厂模式就告一段落了。

本回内容介绍

上一回聊到JS单例模式(singleton),做了一道题,内容不多,比较容易理解。
介一回嘞,聊聊工厂模式,之前聊到过工厂模式,这回聊深入点儿,可能会比较抽象,不过好在实际开发中使用还算广泛,理解起来会比较容易,开始咯:

1. 简单工厂

比如我们创建一个会员系统,有会员和管理员两种角色,每种角色有登录,注销的功能,
这里需要引入之前讲过的接口类,如下:

// 用户类
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:

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();

这个例子有点略复杂,在上一个例子的基础上做了抽象类,还复习了装饰者模式,如果感觉晕菜,可以跳过。
这里其实还可以进一步优化,达到高聚类低耦合,这里工厂模式就告一段落了。


装个逼先。今天看优酷放出了新版嘻哈四重奏,一看没有了原版人马,就算是笑点也笑不起来了,算了换一个剧看,啊呃~~

这一回聊的内容比较绕脑袋,反正感觉晕菜的话就启动囫囵吞枣模式,想不通的先停下,以后再回过来看或许就恍然大悟,
下面的内容,跟上一回一样,就一道题好了。

题目:快速排序

这个快速排序比较基础,网上很多,这里我就把注释写清楚一点,方便大家理解:

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

网上找的例子,注释写的还算清楚吧,难度不大,跟上一回一样,当娱乐消遣。

这一回,主要聊了工厂模式,并且将前面的内容融合了进去,复习了继承,接口,单例模式,装饰者模式,涉及了一些简单的业务逻辑,对于刚接触面向对象,设计模式的童鞋稍微有点难度~~
下一回,就聊用的比较频繁的一个设计模式,门面模式。

客观看完点个赞,推荐推荐呗,嘿嘿~~

注:此系飞狐原创,转载请注明出处

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86151.html

相关文章

  • 飞狐JavaScript设计模式系列06

    本回内容介绍 上一回聊到JS中模拟接口,装饰者模式,掺元类,分析了backbone的继承源码,感觉还好吧! 介一回,偶们来聊一下在JS单例模式(singleton),单例模式其实运用很广泛,比如:jquery,AngularJS,underscore吖虾米的都是单例模式,来吧,直接开始咯: 1. 单例模式 保证一个类只有一个实例,从全局命名空间里提供一个唯一的访问点来访问该对象。其实之前写过的对象...

    hiYoHoo 评论0 收藏0
  • 飞狐JavaScript设计模式系列02

    摘要:本回内容介绍上一回聊到数据类型,简单的过了一遍,包括个数组新特性等,这一回来聊聊对象,结合数组来实战一些例子,在做题中成长,记忆会更深刻,来吧,开始咯创建实例的方式有两种使用操作符后跟构造函数飞狐使用对象字面量表示法飞狐也可以飞狐这种写法与 本回内容介绍 上一回聊到JS数据类型,简单的过了一遍,包括9个数组新特性等,这一回来聊聊Object对象,结合数组来实战一些例子,在做题中成长,记...

    tangr206 评论0 收藏0
  • 飞狐JavaScript设计模式系列11

    摘要:桥接模式之特权函数特权函数,用一些具有特权的方法作为桥梁以便访问私有空间,可以回忆一下之前的系列。连续自然数分组,计算最多组的个数将至这个连续自然数分成组使每组相加的值相等。个数组中数字最多的一组有个此时的和为。 本回内容介绍 上一回,聊了适配器模式,图片预加载,介一回,聊桥接模式(Bridge),跟之前一样,难度比较小,桥接模式将抽象部分与它的实现部分分离,通过桥接模式联系彼此,同时...

    wanglu1209 评论0 收藏0
  • 飞狐JavaScript设计模式系列10

    摘要:本回内容介绍上一回,聊了代理模式,虚拟代理,图片懒加载,介一回,也比较容易,适配器模式,用一个新的接口对现有类的接口进行包装,处理类与的不匹配。这一回,主要聊了适配器模式,图片预加载,主要还是理解下一回,聊一聊桥接模式,顺便做一做计算题。 本回内容介绍 上一回,聊了代理模式,虚拟代理,图片懒加载,介一回,也比较容易,适配器模式(Adapter),用一个新的接口对现有类的接口进行包装,处...

    yexiaobai 评论0 收藏0
  • 飞狐JavaScript设计模式系列14

    摘要:本回内容介绍上一回,聊了聊状态模式,并介绍了一下介一回,聊链式编程,模拟一下,再模拟一下封装一个库。这一回,主要聊了链式调用,模拟了,尤其是,希望大家能喜欢这次代码分享。下一回,聊一聊的策略模式。 本回内容介绍 上一回,聊了聊状态模式(State),并介绍了一下vue.js;介一回,聊链式编程,模拟一下jQuery,再模拟一下underscore.js,封装一个库。 1. 链式调用 (...

    fox_soyoung 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<