【Javascript设计模式】第四课 幽灵工厂——抽象工厂模式

在JavaScript中abstract是一个保留字,所谓的抽象类是一种声明但是不能使用的类,当你使用时就会报错,这时我们可以手动将错误抛出;
  1. var Car = function(){};
  2. Car.prototype = {
  3. getPrice : function () {
  4. throw new Error("抽象方法不能调用");
  5. },
  6. getSpeed : function () {
  7. throw new Error("抽象方法不能调用");
  8. }
  9. };
如果调用的话,使用debug调试得出
  1. var car = new Car();
  2. car.getPrice();//Car is not defined

我们创建的这个Car类,其实什么都不能做,类中没有定义属性,原型的方法也不能使用。但是在继承上很有用,因为定义了一个类,并且定义了该类所具备的方法,如果在子类中继承父类,没有重写这些方法,那么当调用时没有找到这些方法就会报错。

对于抽象类有一个对应的模式——抽象工厂模式
  1. /*******************************************
  2. * 抽象工厂模式
  3. ******************************************/
  4. var VehicleFactory = function (subType, superType) {
  5. //判断抽象工厂中是否有该抽象类
  6. if(typeof VehicleFactory[superType] === 'function'){
  7. //定义一个缓存类
  8. function F(){};
  9. //继承父类的属性和方法
  10. F.prototype = new VehicleFactory[superType]();
  11. //将子类constructor指向子类
  12. subType.constructor = subType;
  13. //子类原型继承父类
  14. subType.prototype = new F();
  15. }else{
  16. throw new Error('未创建该抽象类');
  17. }
  18. }
  1. //定义一个小汽车类
  2. VehicleFactory.Car= function () {
  3. this.type = 'car';
  4. }
  5. VehicleFactory.Car.prototype = {
  6. getPrice : function(){
  7. throw new Error('未创建该抽象类');
  8. },
  9. getSpeed : function () {
  10. throw new Error('未创建该抽象类');
  11. }
  12. }
  13. //定义一个公交车类
  14. VehicleFactory.Bus= function () {
  15. this.type = 'bus';
  16. }
  17. VehicleFactory.Bus.prototype = {
  18. getPrice : function () {
  19. throw new Error('未创建该抽象类');
  20. },
  21. getSpeed : function () {
  22. throw new Error('未创建该抽象类');
  23. }
  24. }
从上面可以看到抽象工厂其实就是一个实现子类继承父类的方法,在这个方法中我们需要通过传递子类以及要继承父类(抽象类)的名称,并且在抽象工厂方法中添加了一次对抽象类存在性的判断,如果存在,则将子类继承父类的方法,然后子类通过寄生式继承。
测试如下:
  1. var BMW = function (price, speed) {
  2. this.price = price;
  3. this.speed = speed;
  4. }
  5. VehicleFactory(BMW,'Car');
  6. BMW.prototype.getPrice = function () {
  7. return this.price;
  8. }
  9. BMW.prototype.getSpeed = function () {
  10. return this.speed;
  11. }
  12. var bmw = new BMW(1000,100);
  13. console.info(bmw.getSpeed());
  14. console.info(bmw.getPrice());
抽象工厂模式、工厂方法模式以及简单工厂模式的异同点及其关系
    简单工厂,工厂方法以及抽象工厂都属于设计模式中的创建型模式,其主要功能都是帮助我们把对象实例化部分抽取出来,优化了系统的架构,增强了系统的扩展性。

三者的共同点是:

1、都有两种作用不同的类:产品类和工厂类。其中,工厂类在自己的方法中实例化产品类(即使用new命令生成产品类的对象),并将生成的产品类的对象提供给外部使用。

2、创建的过程,都是类似的:工厂类得到一个标志(可以由程序输入,也可以读取配置文件中的内容),返回一个产品对象。 

三者的不同点

1、简单工厂

简单工厂方法中,包括一个“抽象产品类(该类可以是接口Interface,也可以是实际的类Class),所有需要的产品类都是该抽象产品类的子类(如果是接口的话,那么就是说所有产品类都继承了该接口)。

简单工厂一般只包含一个具体的工厂类,由该工厂类生成所有的产品类的对象。生成产品类的方法,其内部一般是类似于switch的结构,根据输入的标志,选择创建不同类型的对象。由于不知道创建的对象到底是哪个类的,所以方法的返回值的类型是抽象产品类

 

2、工厂方法

抽象工厂中,包括“抽象工厂类抽象产品类,同时包含不只一个工厂类。所有的工厂类都必须是抽象工厂类的子类,所有的产品都必须是抽象产品类的子类。

和简单工厂比起来,工厂方法一般是从抽象工厂开始的。一般都是在抽象工厂类中提供一个静态方法,由该方法根据输入的标志,生成不同的具体工厂类,然后由具体的产品类生成具体的产品。注意,一个具体工厂类只能生成一种具体的产品类的对象,不同的具体工厂生成不同的产品,而不是像简单工厂中那样,一个工厂类可以生成多种不同产品类的对象。可以这么理解,在选择不同的具体工厂类的时候,就选择了生成的产品,相对于简单工厂,相当于将选择产品的动作提前了。

因为不知道创建的具体工厂类到底是哪一个,所以生成具体工厂类的静态方法的返回值的类型是“抽象工厂类。具体工厂类生成产品类的方法,返回值的类型也要求是抽象产品类(因为前端调用的时候,需要使用同样的代码来访问)。 

3、抽象工厂

抽象工厂和工厂方法很类似,区别如下: 

工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。   
一个抽象工厂类,可以派生出多个具体工厂类。   
每个具体工厂类只能创建一个具体产品类的实例。 

抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。   
一个抽象工厂类,可以派生出多个具体工厂类。   
每个具体工厂类可以创建多个具体产品类的实例。       
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。   
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个







posted @ 2016-10-16 21:22  endy_zhu  阅读(478)  评论(0编辑  收藏  举报