前言
设计模式填坑系列,紧接前文(距离上次写笔记又过去了一个多月,我也不知道怎么加班加着加着就一个月了-_-!)
正文
定义
工厂模式是指提供一个创建对象的接口而不保留具体的创建逻辑,可以根据输入类型创建对象。让子类自行决定实例化哪一种工厂类,实际的创建对象过程在子类中进行。在创建相似子类的时候,执行重复操作。(觉得我说的太抽象没关系,马上就到举例子环节)
具体实现
前面的描述可能还是稍显抽象,举个游戏里面的例子,我们需要实现一个生产游戏角色的RoleMaker
工厂,达到以下目的:
var warrior = RoleMaker.factory('warrior')//生产一个战士
var mage = RoleMaker.factory('mage')//生产一个法师
var priest = RoleMaker.factory('priest')//生产一个牧师
warrior.introduce()// 输出 '我是一个战士,我的特长是近战'
mage.introduce()// 输出 '我是一个法师,我的特长是魔法'
priest.introduce()// 输出 '我是一个牧师,我的特长是治疗'
在这里,我们可以看到形如var warrior = RoleMaker.factory('warrior')
的语句,就是使用RoleMaker
工厂生产了一个战士的过程,这里的战士
,法师
,牧师
都是角色
的一个子类。
接下来就是如何实现上面的RoleMaker
类,最核心的思想还是原型链继承(忘记的同学请自行补课,磨刀不误砍柴工),具体的实现代码如下:
//父类
function RoleMaker() {
// 这里是父类的属性
}
RoleMaker.introduce = function () {
return '我是一个' + this.type + ',我的特长是' + this.specialty
}
//工厂方法
RoleMaker.prototype.factory = function (type) {
var role;
// 这里我们直接把子类构造函数都保存在父类的静态属性中,这样的好处是不污染全局命名空间,同时方便查找。实际上当然也可以直接用`switch-case`实现
if (typeof (RoleMaker[type]) !== "function") {
//对未指定子类的处理,这里是直接抛出错误,也可以为未指定类型做默认值处理
throw {
name: 'Error',
message: type + 'does not exist'
}
}
if (typeof (RoleMaker[type].prototype.introduce !== "function")) {
// 判断是否已经实现继承,注意只继承一次,当然由于只是原型链继承这里判断条件也可以用`RoleMaker[type].constructor===RoleMaker`
RoleMaker[type].prototype = new RoleMaker()
}
role = new RoleMaker[type]() //实例化,也就是实际创建对象的过程
return role
}
// 每个子类的构造函数
RoleMaker.warrior = function () {
this.type = "战士",
this.specialty = "近战"
}
RoleMaker.mage = function () {
this.type = "法师",
this.specialty = "魔法"
}
RoleMaker.priest = function () {
this.type = "牧师",
this.specialty = "治疗"
}
以上代码比较简单,来回顾下前文说道的几个特点:
- 使用者只需要知道特定子类的名称就可以直接生产对应的子类,无需知道具体实现逻辑
- 实际的创建对象过程在子类中进行
- 在创建相似子类的时候,执行重复操作(每个子类只做一次的继承)
补充一个实例
实际上,js的Object()
函数,就很符合工厂模式的特征:
var n = Object(1)
n.constructor === Number
var s = Object('1')
n.constructor === String
var b = Object(true)
n.constructor === Boolean
小结
自我感觉设计模式系列由于还是处于学习阶段,实践经验相对较少,所以写起来还是偏向于读书笔记类,所以可能有很多地方都显得粗糙。权当做先占个坑,等后续有更深入理解再回来补上。
然后惯例感谢之前的热心读者,尤其是为我指出错误的小伙伴。
然后依然是每次都一样的结尾,如果内容有错误的地方欢迎指出;如果对你有帮助,欢迎点赞和收藏,转载请征得同意后著明出处,如果有问题也欢迎私信交流,主页添加了邮箱地址~溜了