设计模式之工厂模式

工厂模式是一种最常用的实例化对象模式,是用工厂方法代替new操作的一种模式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。因为工厂模式就相当于创建实例对象的new,在JavaScript中通常会使用new关键字来实例化对象,如A:a = new A(),工厂模式也是用来创建实例对象的,所以,以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。

设计意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行

主要解决的问题:在不同条件下创建不同实例时,主要解决接口选择的问题

工厂模式就是使用工厂方法代替new操作创建对象实例的一种模式。即把new操作交给其他对象来做。

最简单的工厂模式程序实例:

1
2
3
4
5
6
7
8
class A {
constructor() {}
}

// 创建class A实例的工厂函数
var createA = () => {
return new A()
}

于是,创建一个class A的实例:

1
var a = createA()

这是最简单的工厂模式,只用于创建一种实例对象。这么简单的工厂模式是没有任何意义的,因为,要创建class A的实例直接new就好了,没必要引入createA,所以这里的createA是多余的。

现在,来看下真正有用的工厂模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class A {
constructor() {}
}

class B {
constructor() {}
}

class C {
constructor() {}
}

// 工厂函数
var factory = (type) => {
if (type === 'A') {
return new A()
} else if (type === 'B') {
return new B()
} else if (type === 'C') {
return new C()
}
}

这样,就可以使用工厂函数(factory)创建不同的类的实例了。想创建那个类的实例,只要知道其类型就可以了,剩下的操作都交给工厂函数(factory)。 而且,如果想增加一个类型,只要扩展一个工厂类就可以了。

接下来我们再看一个在网页中使用的一个实例。假如我们想在网页面里插入一些元素,而这些元素类型不固定,可能是图片,也有可能是连接,甚至可能是文本,根据工厂模式的定义,我们需要定义工厂类和相应的子类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
var page = (function(){

var dom = {};

//子类1:处理文本
dom.Text = function(){
this.insert = function(where, text){
var txt = document.createTextNode(text);
where.appendChild(txt);
}
};

//子类2:处理链接
dom.Link = function(){
this.insert = function(where, url){
var link = document.createElement("a");
link.href = url;
link.appendChild(document.createTextNode(url));
where.appendChild(link);
}
};

//子类3:处理图片
dom.Image = function () {
this.insert = function (where, url) {
var img = document.createElement('img');
img.src = url;
where.appendChild(img);
};
};

//创建函数
dom.create = function(type){
return new dom[type];
};

return {
dom: dom
}

})();

var t = page.dom.create('Text');
t.insert(document.body, "新建文本节点");