工厂 模式

概念

工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替`new`操作的一种模式。工厂模式就相当于创建实例对象的`new`,我们经常要根据类`Class`生成实例对象,如`A a=new A()` 工厂模式也是用来创建实例对象的,**所以以后`new`时就要多个心眼,是否可以考虑使用工厂模式**,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。

示例

现在你要得到一个汉堡,你是跟服务员要(买)一个,还是自己动手做一个?这个问题,服务员就是工厂方法,而动手做一个其实就是`new A()`。

另外从快餐店考虑,你想要提供一个汉堡,是让服务员(工厂方法)做出来(`new A()`)给客户,还是让客户自己做一个汉堡?

UML类图

代码:

class Product {
    constructor(name) {
        this.name = name
    }
    init() {
        alert('init')
    }
    fun1() {
        alert('fn1')
    }
    fun2() {
        alert('fn2')
    }
}

class Creator {
    create(name) {
        return new Product(name)
    }
}

// 测试
let creator = new Creator()
let p = creator.create('p1')
p.init()
p.fn1()

对比刚开始的例子,`Product`就是汉堡,`Creator`就是服务员,很好理解吧。

但是在日常工作编码中,不会再额外增加`Creator`的类了,`create`直接当做静态的函数就行了。

使用场景

工厂模式在日常使用非常多,凡是用到`new`的地方,都要考虑是否需要工厂模式。

 jQuery

`$('div')`

模拟代码,`$`就是一个工厂

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.$ = function (selector) {
    return new jQuery(selector)
}

做一个对比,如果开放给用户的不是`$`,然后让用户自己去`new jQuery(selector)`,带来的问题:

- 操作复杂,代码量增加,如`$('div').append($('#p1')).html()`这种操作将变得冗长繁琐

- 一旦构造函数`jQuery`有变化,使用者都受牵连,不符合开闭原则

React.createElement

在 React 中经常使用 JSX 语法

```jsx
var profile = <div>
  <img src="avatar.png" className="profile" />
  <h3>{[user.firstName, user.lastName].join(' ')}</h3>
</div>;
```

这是一种语法糖,编译之后就会是:

```js
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, chilren) {
    // ...省略内部代码...
}
React.createElement =  function (tag, attrs, children) {
    return new Vnode(tag, attrs, chilren)
}

vue 异步组件

在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会被触发,且会把结果缓存起来供未来重渲染。例如:

Vue.component('async-example', function (resolve, reject) {
  setTimeout(function () {
    resolve({
      template: '<div>I am async!</div>'
    })
  }, 1000)
})

这个工厂函数会收到一个 resolve 回调,这个回调函数会在你从服务器得到组件定义的时候被调用。你也可以调用 reject(reason) 来表示加载失败。

1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值