组织代码将为我们节省大量的痛苦。使用对象导向编程的功能(https://andsky.com/tech/tutorials/js-objects-prototypes-classes),我们可以使用某些设计模式来实现更好的可读性,减少冗余,并在必要时创建抽象。
工厂模式是一种类型的面向对象模式,它遵循DRY方法,正如其名称所示,对象实例是通过使用工厂来为我们制作所需的对象来创建的。
让我们来看看一个非常简单的例子,使用工厂模式来组装一个合金器
对象. 为了做到这一点,我们首先需要制造制造合金器
部件的工厂:
1class TailFactory {
2 constructor(props) {
3 this.tailLength = props.tailLength;
4 }
5};
6
7class TorsoFactory {
8 constructor(props) {
9 this.color = props.color;
10 }
11};
12
13class HeadFactory {
14 constructor(props) {
15 this.snoutLenth = props.snoutLenth;
16 }
17};
现在,我们创建了一个类,作为实际工厂类和用户之间的中间人,让我们称之为ReptilePartFactory
:
1class ReptilePartFactory {
2 constructor(type, props) {
3 if(type === "tail")
4 return new TailFactory(props);
5 if(type === "torso")
6 return new TorsoFactory(props);
7 if(type === "head")
8 return new HeadFactory(props);
9 }
10};
让我们现在继续进行并组装实际的鱼,并使用ReptilePartFactory
为我们提供所需的零部件:
1let alligator = {};
2let alligatorProps = {
3 tailLength : 2.5,
4 color: "green",
5 snoutLenth: 1
6};
7
8//gets a tail from the tail factory
9alligator.tail = new ReptilePartFactory("tail", alligatorProps);
10
11//gets a torso from the torso factory
12alligator.torso = new ReptilePartFactory("torso", alligatorProps);
13
14//gets a head from the head factory
15alligator.head = new ReptilePartFactory("head", alligatorProps);
看看上面的图案,似乎我们可以使用相同的ReptilePartFactory
来创建对象的零部件。
因此,使用工厂模式给了我们一定的优势:
- 动态对象创建:可以在运行时决定对象类型的情况下使用
- 抽象:用户从不真正需要访问实际对象的构造器
- 可重复使用/维护:相同的工厂可以用于类似的对象,它允许我们轻松地添加/删除新的对象类,而无需更改大量的代码
现在我们对工厂模式有了一些了解,让我们来探索写出更好的工厂模式代码。
上面的例子使用一个如果梯子来找出基于用户输入来调用哪个工厂。这是一个简单的实现,直观的,不太开放的变化。如果我们有新的部件要添加以后,那么我们将不得不干扰ReptilePartFactory
。这是违反SOLID原则,其中说软件实体(类,模块,函数等)应该开放扩展,但关闭修改
。
我们如何在一个对象中存储工厂类,并通过使用我们想要的部分作为钥匙来调用所需的零部件工厂?首先我们需要注册工厂,这将是简单的:
1let registeredPartFactories = {};
2registeredPartFactories['tail'] = class TailFactory{
3 ...
4};
5
6registeredPartFactories['torso'] = class TorsoFactory {
7 ...
8};
9
10registeredPartFactories['head'] = class HeadFactory {
11 ...
12};
现在,抽象层可以这样称呼工厂:
1class ReptilePartFactory {
2 constructor(type, props) {
3 return new registeredPartFactories[type](props);
4 }
5};
这种方法更清洁,可以扩大我们的工厂,而不会影响ReptilePartFactory
中的代码。
结论
还有几种其他面向对象的模式也增加了可读性和质量,所以在使用工厂模式之前,请检查是否有真正的要求。如果您要重复创建类似类型的对象,并且还需要一个层来使用这些对象创建新实例,同时为创建逻辑提供一些抽象水平,那么是的 - 工厂模式是一个很好的选择。