工厂模式
- 将new操作单独封装
- 遇到new时,就要考虑是否该使用工厂模式
示例:
- 你去购买汉堡,直接点餐,取餐,不用自己亲手做
- 商店要“封装”做汉堡的工作,做好直接给买者
class Product {
constructor(name) {
this.name = name
}
init() {
alert('init')
}
func1() {
alert('func1')
}
func2() {
alert('fun2')
}
}
class Creator {
create(name) {
return new Product(name)
}
}
// 测试
let creator = new Creator()
let p = creator.create('p1')
p.init()
p.func1()
场景:
jQuery - $('div')
React.createElement
- vue异步组件
jQuery
$('div')
和new $('div')
有何区别?- 第一种是工厂形式,第二种创建实例
使用的第二种的话:
- 书写麻烦,jQuery的链式操作将成为噩梦
- 一旦jQuery名字变化,将是灾难性的
class jQuery {
constructor(selector) {
let slice = Array.prototype.slice
let dom = slice.call(document.querySelectorAll(selector))
let len = dom ? dom.length : 0
for (let i = 0; i < len; i++) {
this[i] = dom[i]
}
this.length = len
this.selector = selector || ''
}
append(node) {
}
addClass(name) {
}
html(data) {
}
// 此处省略若干API
}
window.$ = funciton (selector) {
return new jQuery(selector)
}
阅读经典lib源码的意义:
- 学习如何实现功能
- 学习设计思路
- 强制自己写代码,刻意训练
创新和拿来主义:
- 拿来主义比较高效😂
React.createElement
var profile = <div>
<img src="avatar.png" className="profile" />
<h3>{[user.firstName, user.lastName].join(' ')}</h3>
</div>
编译后为:
var profile = React.createElement("div", null,
React.createElement("img", { src: "avatar.png", className: "profile" }),
React.createElement("h3", null, [user.firstName, user.lastName].join(" "))
)
React.createElement
就是工厂函数
源码简化演示:
class Vnode(tag, attrs, children) {
// ... 省略内部代码...
}
React.createElement = function (tag, attrs, children) {
return new Vnode(tag, attrs, children)
}
vue异步组件
Vue.component('async-example', function (resolve, reject) {
setTimeout(funciton () {
resolve({
template: '<div>I am async!</div>'
})
}, 1000)
})
设计原则验证
- 构造函数和创建者分离
- 符合开放封闭原则