【JS设计模式笔记】神奇的魔术师-简单工厂模式(创建型)
简单工厂模式(Simple Factory):又叫静态工厂方法,由一个工厂对象决定创建某一种产品对象类的实例。主要用来创建同一类对象。
第一次需求
开发一个登录模块的需求,用户名输入框如果输入的内容不符合规范就自定义一个警告框警示一句:‘用户名不能多于16个字母或数字’
var LoginAlert = function(text) {
this.content = text;
}
LoginAlert.prototype.show = function() {
// 显示警告框
}
var useNameAlert = new LoginAlert('用户名不能多于16个字母或数字');
useNameAlert.show();
关于用户密码输入错误也有一句提示:‘输入的密码不正确’。
var passwordAlert = new LoginAlert('输入的密码不正确');
passwordAlert.show();
又有一个需求,当用户登录时,如果出现用户名不存在,也提示一句:‘您的用户名不存在,请重新输入’。
这个时候又得重新创建一个类。
var LoginConfirm = function(text) {
this.content = text;
}
LoginConfirm.prototype.show = function() {
// 显示确认框
}
var loginFailConfirm = new LoginConfirm('您的用户名不存在,请重新输入');
loginFailConfirm.show();
现在登录成功后,又得需要一个自定义提示框,除了有确定取消按钮,也提示一句话:’欢迎回来‘。
这又是一个新的类:
var LoginPrompt = function(text) {
this.content = text;
}
LoginPrompt.prototype.show = function() {
// 显示提示框
}
现在需要开发一个注册模块,用需要用到提示框相关的功能。’
如果类太多,提供一个
以前的登录模块有三个类,分别为LoginAlert、LoginConfirm、LoginPrompt,还是以Login为前缀,现在来写个简单工厂,也即是封装一个函数,我们用这个函数创建我们需要的对象为我所用即可。这样其他人不用关心创建这个对象用到哪些基类,这样其他人只需要记住这个函数就可以了。这个函数通常也被称为工厂函数。
举个例子,比如一个会变魔术的魔法师,你想要魔法师给你变礼物,但是你不关心魔法师用什么来变的,你只需要这位魔法师就可以了。
例如体育商点售卖体育器材,里面有很多体育用品,及相关介绍等,当你需要买篮球的时候,只需要告诉售货员就可以,他会帮你找找到你想要的东西。
// 篮球基类
var Basketball = function() {
this.intro = '篮球盛行于美国';
}
Basketball.prototype = {
getMember: function() {
console.log('每个队伍需要5名队员');
},
getBallSize: function() {
console.log('篮球很大');
}
}
// 足球基类
var Football = function() {
this.intro = '足球很流行';
}
Football.prototype = {
getMember: function() {
console.log('每个队伍需要11名队员');
},
getBallSize: function() {
console.log('足球很大')
}
}
// 网球基类
var Tennis = function() {
this.intro = '网球介绍';
}
Tennis.prototype = {
getMember: function() {
console.log('每个队伍需要1名队员')
},
getBallSize: function() {
console.log('网球很少');
}
}
// 运动工厂
var sportsFactory = function(name) {
switch(name) {
case 'NBA':
return new Basketball();
case 'worldcup':
return new Football();
case 'frenchopen':
return new Tennis();
}
}
// 示例
var footBall = sportsFactory('worldcup');
console.log(footBall);
console.log(footBall.intro);
footBall.getMember();
那么自定义弹框可以这样实现:
var popFactory = function(name,text) {
switch(name) {
case 'alert':
return new LoginAlert(text);
case 'confirm':
return new LoginConfirm(text);
case 'prompt':
return new LoginConfirm(text);
}
}
var useNameAlert = popFactory('alert','用户名不能多于16个字母或数字');
useNameAlert.show()
一个对象有时也可代替许多类
从上面LoginAlert、LoginConfirm、LoginConfirm三个类,有很多地方是相同,比如都有关闭按钮,都有提示文案等,我们也可以抽象提取出来公用的,也可以用简单工厂的方式来实现它们。
举个例子,比如我想创建一些书,那些书都有一些相似的地方,比如目录、页码等。也有一些不相似的地方,比如书名、出版时间、书的类型等,对于创建的对象相似的属性好处理,对于不同的属性就要有针对性的进行处理了,比如我们将不同的属性作为参数传递进来处理。
// 工厂模式
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','2004','js');
var book2 = createBook('java book','2005','java');
book1.getName(); // js book
book2.getName(); // java book
我们对上面三个弹框类进行优化:
function createPop(type,text) {
// 创建一个对象,并对对象扩展属性和方法
var o = new Object();
o.content = text;
o.show = function() {
// 显示方法
}
if(type == 'alert') {
// 警示框差异部分
}
if(type == 'prompt') {
// 提示框差异部分
}
if(type == 'confirm') {
// 确认框差异部分
}
// 将对象返回
return o;
}
// 创建警示框
var userNameAlert = createPop('alert','用户名只能是26个字母或数字');
你的理解决定你的选择方式
第一种是通过类实例化对象创建的,第二种是通过创建新的对象然后包装增强其属性和功能来实现的。