上一回聊到JS单例模式(singleton),作了一道题,内容很少,比较容易理解。
介一回嘞,聊聊工厂模式,以前聊到过工厂模式,这回聊深刻点儿,可能会比较抽象,不过好在实际开发中使用还算普遍,理解起来会比较容易,开始咯:javascript
好比咱们建立一个会员系统,有会员和管理员两种角色,每种角色有登陆,注销的功能,
这里须要引入以前讲过的接口类,以下: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:设计模式
这里要用到以前写的继承类了,写一个用户基类,还要考虑到每一个用户和管理员分别有不一样的权限,那么咱们能够再作一次工厂解耦,细化粒度,以下:数组
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
不一样的用户组有不一样的角色,不一样的角色拥有不一样的权限,以下:测试
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
网上找的例子,注释写的还算清楚吧,难度不大,跟上一回同样,当娱乐消遣。
这一回,主要聊了工厂模式,而且将前面的内容融合了进去,复习了继承,接口,单例模式,装饰者模式,涉及了一些简单的业务逻辑,对于刚接触面向对象,设计模式的童鞋稍微有点难度~~
下一回,就聊用的比较频繁的一个设计模式,门面模式。
客观看完点个赞,推荐推荐呗,嘿嘿~~
注:此系飞狐原创,转载请注明出处