【D1n910】第3章 神奇的魔术师——简单工厂模式《JavaScript 设计模式》(2[1/8]/6)
正常操作,正常分析,大家好,我是D1n910。
今天继续来学习 《JavaScript 设计模式》的第二篇 创建型设计模式 的
第3章 写的都是看到的——面向对象编程。
这是一个连续的读书笔记,所以如果你之前的内容没有看的话,请务必一定要去看。


这里再次感谢 《Javascript 设计模式》及其作者 张荣铭,专栏内容是在它的基础上生成的。

第二篇 创建型设计模式
创建型设计模式是一类处理对象创建的设计模式。
通过某种方式控制对象的创建来避免基本对象创建时可能导致设计上的问题或增加设计上的复杂度。
第 3 章 神奇的魔术师——简单工厂模式
3.1、工作中的第一次需求(p34)
作者列举了一种场景来说明功能相似的不同类可以放到一起。
程序猿A在工作中,陆续接到下面的需求,并在工程代码里书写。
需求一:针对登录模块,如果用户输入用户名不符合规范,则弹出一个警告,“用户名不能多于16个字母或数字”。
var LoginAlert = function (text) {
this.content = text
}
LoginAlert.prototype.show = function(){
// 显示提示框
}
var userNameAlert = new LoginAlert('用户名不能多于16个字母或数字')
userNameAlert.show()
需求二:针对登录模块,如果用户输入密码错误,则弹出一个警告,“输入的密码不正确”。
var passswordAlert= new LoginAlert('输入的密码不正确')
passswordAlert.show()
需求三:针对登录输入框,如果用户登录用户名不存在,则弹出一个警告,“用户名不存在,请重新输入”。—— 但是这时候的警示框中添加一个注册按钮。
程序猿A想,之前的没办法复用了。于是重新创建了一个类。
var LoginConfirm= function (text) {
this.content = text
}
LoginConfirm.prototype.show = function(){
// 显示提示框
}
var LoginFailConfirm = new LoginConfirm('您的用户名不存在,请重新输入')
LoginFailConfirm.show()
需求四:登录成功以后,弹出一个自定义提示框,除了有确定取消按钮,也提示一句:“欢迎回来,请出入您今天的心情吧。”
程序猿A想,之前的没办法又复用了。于是又重新创建了一个类。
var LoginPrompt= function (text) {
this.content = text
}
LoginPrompt.prototype.show = function(){
// 显示提示框
}
……
这时候程序猿 B 也在写相关的内容,他在写注册模块,也要用到提示框,当他向程序猿 A 要相关代码时,不乐意了。
他觉得这里的类太多了,而且都是用 Login 作为前缀的,希望程序猿 A 写一个【简单工厂】给他。
3.2、如果类太多,那么提供一个(p35)
3.1 里创建了三种基类,每次用的时候要找到对应的基类,而且这里的类名还是带 Login 前缀的,在注册模块用起来,也感觉很奇怪。
如果把这些基类封装起来,放到一个工厂里,把需要的类型告诉给工厂,工厂自动吐出需要的类。用的时候也只需要记住对应的工厂即可。
比如刚刚的函数,都是弹窗的,可以放到自定义弹窗工厂里。
var PopFactory = function(name, str) {
switch(name) {
case 'alert':
retrun new LoginAlert(str);
case 'confirm':
return new LoginConfirm(str);
case 'prompt':
return new LoginPrompt(str);
}
}
var resigerConfirm = PopFactory('confirm', '该用户名已注册过')
resigerConfirm.show()
3.3、一个对象有时也可代替许多类(p37)
上面的三个类其实有很多地方时一样的,可以抽离出来公用。用简单工厂方式实现他们。
这里的对象工厂模式是没有类的,无需做任何继承,只需要创建对象即可。然后对这个对象进行大量拓展方法和属性,并在最终对象返回出来。
比如创建书,它的属性有书名,出版时间,类型,那么可以用工厂模式实现。
// 工厂模式
function createBook(name, time, type) {
var o = new Object();
o.name = name;
o.time = time;
o.type = type;
o.getName = function() {
console.log(this.name)
}
return o
}
var book1 = createBook('js book', 2014, 'js')
var book2 = createBook('css book', 2013, 'css')

这里很像寄生式继承,不过这里的 o 没有继承任何类或者对象。
3 个类改成一个工厂模式也一样,只需要把差异部分提取出来就行。
function createPop(type, text) {
var o = new Object();
o.content = text;
o.show = funtion() {
// 显示方法
};
if (type == 'alert') {
// 警示框差异部分
}
// ……
// 将对象返回
return 0
}
// 创建警示框
var userNameAlert = createPop('alert', '用户名只能是26个字母和数字')
(其实上面的内容,用类也可以实现啊,所以感觉很鸡肋的样子!)
3.4、你的理解决定你选择的方式
这两个工厂是有区别的,一个是通过类的实例化对象创建;一个是创建一个新对象,然后进行包装增加其属性和功能实现的。
前者如果有继承父类的话,那么父类的方法是能共用的。
而后面寄生方式创建的对象都是一个新的个体,所以他们的方法就不能共用了。
要按照具体需求来决定自己要的方法。
本章End
感觉简单工厂好水的样子?
确实很简单!
D1n910
2012.02.13 15:09 写于福永