工厂模式

"Hello World, Hello Blog"

Posted by wudimingwo on December 15, 2018

工厂模式定义 抄一遍: 定义: 工厂模式定义创建对象的接口, 但是让子类去真正的实例化. 也就是工厂方法将类的实例化延迟到子类.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 // 1. 原始模式
            
            var plane = {
              width : 100,
              height : 100,
              blood : 100,
              touch : function () {
              	this.blood += 15;
              	if(this.blood  <= 0) {
              	  console.log('die');
              	}
              }
            }
            
            //无法满足后续需求?
            // 因为会有相似属性?
            // 只要有相似,写代码的时候, 只要感觉有相似的感觉,
            // 我们就可以想办法解决.
            // 把所有 con+c con+v 的需求 都用某种模式搞定?
            

简单工厂模式

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
// 2. 构造函数模式 // 类
            function SamllPlane () {
            	this.width = 100;
            	this.height = 100;
            	this.name = 'smallPlane';
            	this.blood = 100;
            	this.touch = function () {
            		this.blood -= 100;
            		if (this.blood <= 0) {
            			console.log('die');
            		}
            	}
            }
            
            new SmallPlane();
            
            
            function BigPlane () {
              this.width = 150;
              this.height = 200;
              this.name = 'bigPlane';
              this.blood = 200;
              this.touch = function () {
                this.blood -= 100;
                if (this.blood <= 0) {
                  console.log('die');
                }
              }
            }
            
            // 我们试着把这两种整合一下

对比其他方式 1.工厂类集中了所有对象的创建,便于对象创建的统一管理. 2.对象的使用者仅仅是使用产品,实现了单一职责. 3.便于扩展,如果新增了一种业务,只需要增加 相关的业务对象类和工厂类中的生产业务对象的方法, 不需要修改其他的地方. 4.确实违反了开闭原则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function PlaneFactory (type) {// type = 'SmallPlane' | "BigPlane"
            
            	var newPlane = null;
            	switch (type){
            		case type:
            		  newPlane = new SmallPlane();
            			break;
            		case type:
            		  newPlane = new BigPlane();
            			break;
            	}
            	newPlane.die = function () {// 对比原始模式,这就生了一次 con+v
            		console.log('boomb');
            	}
            	
            	return newPlane;
             // 缺陷,生成的实例,无法访问原型, 因为 PlaneFactory 不是真正的构造函数.
            // 不过在上面  BigPlane.prototype = new PlaneFactory() 似乎也能解决.
            }
            
            
            PlaneFactory('SamllPlane');

工厂方法模式 工厂方法模式: 不再有唯一的一个工厂类只创建产品, 而是将不同的产品交给对应的工厂子类去实现. 每个产品由负责生产的子工厂来创造. 如果添加新的产品, 需要做的就是添加新的子工厂和产品, 而不需要修改其他的工厂代码. 抽象工厂模式的组成 1.抽象工厂类: 负责定义创建产品的公共接口. 2.产品子工厂: 继承抽象工厂类,实现抽象工厂类提供的接口. 3.每一种产品有各自的产品类. 特点 抽象工厂模式 步骤1

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<script type="text/javascript">
           
            //抽象工厂模式
            
            function PlaneFactory () {
              
            }
            //子类工厂都可以使用的公共方法.
            PlaneFactory.prototype.touch = function () {
            	
            }
            // 创建对象的接口 // 这个接口定义在函数上,类似jq的工具方法.
            // 如果该接口定义在原型上, 则必须实例化之后才能调用, 跟现实场景模拟不符.
            PlaneFactory.create = function (type) {
            	// 判定是否存在该类型的子类工厂.
            	if (PlaneFactory.prototype[type] == undefined) {
            		throw 'no this constructor'
            	}
            	//实现继承 子工厂继承PlaneFactory 
            	if (PlaneFactory.prototype[type].prototype.__proto__ !== PlaneFactory.prototype) {// 这个条件时判断有没有完成继承
            	  // 问题? 重复继承会怎么样? 继承虽然没什么问题, 但 子工厂的 原型就会被刷新, 有可能会把在外面定义在在该原型的数据抹掉.
            	  PlaneFactory.prototype[type].prototype = new PlaneFactory();
            	}
            	// 创建对象
            	var newPlane = new PlaneFactory.prototype[type]();
                return newPlane;
                // 子工厂可能有需要传参的情况,如果直接在这里传参,
                // 逻辑可能会变得复杂,复杂度会变高, 并且调用的时候,参数太多,不太好用.
            }
            
            // 真正定义子类工厂
            
            PlaneFactory.prototype.SmallPlane = function (x, y) {
              this.x = x;
              this.y = y;
            	this.width = 100;
              this.height = 100;
              this.name = 'smallPlane';
              this.blood = 100;
              this.touch = function () {
                this.blood -= 100;
                if (this.blood <= 0) {
                  console.log('die');
                }
              }
            }
            PlaneFactory.prototype.BigPlane = function () {
            	this.width = 150;
              this.height = 200;
              this.name = 'bigPlane';
              this.blood = 200;
              this.touch = function () {
                this.blood -= 50;
                if (this.blood <= 0) {
                  console.log('die');
                }
              }
            }
            PlaneFactory.prototype.AttackPlane = function () {
            	this.width = 120;
              this.height = 100;
              this.name = 'attackPlane';
              this.blood = 100;
              this.touch = function () {
                this.blood -= 100;
                if (this.blood <= 0) {
                  console.log('die');
                }
              }
                this.attack = function () {
                	console.log('biu');
                }
            }
            
            var oAp = PlaneFactory.create('AttackPlane');
            
        </script>

1.所谓的开闭原则的一个体会. 对修改关闭,对扩展开放. 修改,一般指的是函数, 扩展,一般就是对象. 所以可以认为, 把需要修改函数的需求, 想办法调整结构,调整成对象的扩展需求. 函数里面如果添加内容,一般就是修改了吧?

2.针对上面的抽象工厂模式, 我们试着总结一下结构. 是两层构造函数, 第一层构造函数的原型上可以定义重复性强的一些属性或方法, 留出一个接口,接收一个函数名作为参数,用来调用第二层构造函数. 第二层构造函数继承第一层构造函数.

3. 不同属性的级别,可以用new 实例的时候传不同的值. 不同实例的级别,可以选择不同的子工厂,如果没有,可以添加新的工厂.

如果相似的实例,需要类似的方法,可以定义在子工厂的原型上, 如果是更普遍的方法,可以定义在,父工厂上.