2. JavaScript 设计模式(简单工厂,工厂方法,抽象工厂)

来源:互联网 发布:数据仓库与数据库区别 编辑:程序博客网 时间:2024/05/01 10:09
  1. 简单工厂(simple factory)

简单工厂模式:又叫静态工厂方法,由一个工厂对象觉得创建某一种产品对象类的实例。主要用于创建同一类对象。

  • 简单工厂 uml 图格式如下: 
    这里写图片描述

    由上面的uml图可知,工厂返回的对象是要继承Product类的,但是由于js定义变量是没有指定数据类型,也没有多态。那怎么怎么保证工厂返回的对象都继承Product呢?我自己想到了一个方法。

/** * 披萨基类 * * @constructor */var Pizza = function() {    this.getName = function() {        console.log('披萨类!');        // 抛出错误,模拟抽象类        throw new Error('该类为抽象类,不能条用方法!');    };};/** * 芝士披萨类 * * @constructor */var CheesePizza = function() {};// 继承皮萨类CheesePizza.prototype = new Pizza();// 重写 getName 方法CheesePizza.prototype.getName = function() {    console.log('芝士披萨类');};var ClamPizza = function() {};ClamPizza.prototype = new Pizza();ClamPizza.prototype.getName = function() {    console.log('蛤蜊披萨')};/** * 工厂方法 * * @constructor */var simplePizzaFactory = function(type) {    var pizza = null;    if (type == 'cheese') {        pizza = new CheesePizza();    } else if (type == 'clam') {        pizza = new ClamPizza();    }    var superObj = pizza.__proto__;    if (!superObj instanceof Pizza) {        throw new Error('该类的产品没有继承 Pizza 类!');    }    return pizza;};var cheesePizza = simplePizzaFactory('cheese');cheesePizza.getName(); // console: 芝士披萨类
  • 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
  • 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
  • 利用__proto__这个就保证了工厂返回的类都是继承与Pizza(图为Product)类的。

2.工厂方法(factory method)

通过对产品类的抽象使其创建业务主要负责用于创建多类产品的实例。

  • 工厂方法 uml 图如下: 
    这里写图片描述

  • 工厂类代码,这里只有“纽约pizza工厂”其实还可以有“墨西哥pizza工厂”甚至还可以有其他的。不写了,就举个例子吧。

/** * Pizza 工厂抽象类 * * @constructor */var PizzaFactory = function() {    this.createPizza = function(type) {        throw new Error('该 pizza 工厂类用于继承,不能调用');    };};/** * 纽约 pizza 工厂类 *  * @constructor */var NYPizzaFactory = function() {};NYPizzaFactory.prototype = new PizzaFactory();NYPizzaFactory.prototype.createPizza = function(type) {    var pizza = null;    if (type == 'cheese') {        pizza = NYCheesePizza();    } else if (type == 'clam') {        pizza = NYClamPizza();    }    var superObj = pizza.__proto__;    if (!superObj instanceof Pizza) {        throw new Error('该类的产品没有继承 Pizza 类!');    }    return pizza;};
  • 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
  • 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
  • pizza 类代码
/** * Pizza 抽象类 * * @constructor */var Pizza = function() {    this.getName = function() {        throw new Error('该 pizza 类用于继承,不能调用');    };};/** * 纽约芝士披萨类 * * @constructor */var NYCheesePizza = function() {};NYCheesePizza.prototype = new Pizza();NYCheesePizza.prototype.getName = function() {    console.log('纽约芝士披萨!');};/** * 纽约蛤蜊披萨类 * * @constructor */var NYClamPizza = function() {};NYClamPizza.prototype = new Pizza();NYClamPizza.prototype.getName = function() {    console.log('纽约蛤蜊披萨!');};
  • 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
  • 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

3.抽象工厂模式(abstract factory)

通过对类的工厂抽象使其业务用于对产品类簇的创建。而不是负责创建一类产品的实例。

  • 抽象工厂 uml 图如下: 
    这里写图片描述

将抽象工厂和工厂方法的 uml 图比较一下,可以发现工厂方法用来生成不同的pizza。而抽象工厂则是生产一个一地方的披萨店的所有产品。举个例子,ProductA是pizza,ProductB是薯条。

  • pizza 类代码(和上面的一样,没有区别)
/** * 披萨基类 * * @constructor */var Pizza = function() {    this.getName = function() {        throw new Error('该 pizza 类用于继承,不能调用');    }};/** * 纽约芝士披萨类 * * @constructor */var NYCheesePizza = function() {};NYCheesePizza.prototype = new Pizza();NYCheesePizza.prototype.getName = function() {    console.log('纽约芝士披萨!');};/** * 纽约蛤蜊披萨类 *  * @constructor */var NYClamPizza = function() {};NYClamPizza.prototype = new Pizza();NYClamPizza.prototype.getName = function() {    console.log('纽约蛤蜊披萨!');};
  • 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
  • 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
  • 薯条类代码
/** * 薯条基类 * * @constructor */var Fries = function() {    this.getName = function() {        throw new Error('该薯条类用于继承,不能调用');    };};/** * 配番茄酱的薯条 * * @constructor */var TomatoFries = function() {};TomatoFries.prototype = new Fries();TomatoFries.prototype.getName = function() {    console.log('配番茄酱的薯条');};/** * 配芝士的薯条 *  * @constructor */var CheeseFries = function() {};CheeseFries.prototype = new Fries();CheeseFries.prototype.getName = function() {    console.log('配芝士的薯条');};
  • 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
  • 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
  • 商店工厂类(这里除了纽约,还有其他的商店可以继续写,例如墨西哥。。。)
/** * 商店工厂抽象类 * * @constructor */var StoreFactory = function() {    this.createPizza = function(type) {        throw new Error('该商店工厂类用于继承,不能调用');    };    this.createFries = function(type) {        throw new Error('该商店工厂类用于继承,不能调用');    };};/** * 纽约商店工厂类 *  * @constructor */var NYFactory = function() {};NYFactory.prototype = new StoreFactory();NYFactory.prototype.createPizza = function(type) {    var pizza = null;    if (type == 'cheese') {        pizza = NYCheesePizza();    } else if (type == 'clam') {        pizza = NYClamPizza();    }    var superObj = pizza.__proto__;    if (!superObj instanceof Pizza) {        throw new Error('该类的产品没有继承 Pizza 类!');    }    return pizza;};NYFactory.prototype.createFries = function() {    // 偷个懒不写了};
  • 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
  • 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

4.总结(摘自Head First 设计模式):

  • 所有的工厂都是用来封装对象的创建。
  • 简单工厂,虽然不是真正的设计模式,但仍不失为一个简单的方法,可以将客户程序从具体类解耦。
  • 工厂方法使用继承,把对象的创建委托给子类,子类实现工厂来创建对象。
  • 抽象工厂使用对象组合,对象的创建被实现在工厂接口所暴露的方法中。
  • 所有工厂模式都是通过减少应用程序和具体类之间的依赖促进松耦合。
  • 工厂方法允许类将实例化延迟到子类进行。
  • 抽象工厂创建相关的对象家族,而不需要依赖他们的具体类。
  • 依赖倒置原则,指导我们避免依赖具体类,而要尽量依赖抽象
  • 工厂是很有威力的技巧,帮助我们针对抽象编程,而不要针对具体类编程。
注:此文为转载,原创是 http://blog.csdn.net/willson_l/article/details/72769883
阅读全文
0 0
原创粉丝点击