JavaScript创建型设计模式---抽象工厂模式

参考书籍:JavaScript设计模式
在聊抽象工厂模式之前先谈谈 javascript 的抽象类。javascript的抽象类是一种声明但不能使用的类,当使用时就会报错,javascript 是在类的方法中手动抛出错误来模拟抽象类。

//汽车抽象类,当使用实例对象的方法时会抛出错误
var Car = function () { };
Car.prototype = {
    getPrice: function () {
        return new Error('抽象方法不能调用');
    },
    getSpeed: function () {
        return new Error('抽象方法不能调用');
    }
}

上面car 这个类其实什么也不能做,创建时没有任何属性,原型上的方法也是不能使用的,否则会报错。但是在继承上却是很有用的,因为定义了一种类,并定义了该类所必备的方法,如果子类中没有重写这些方法,那么当调用时就会报错。这一特点是很有必要的,因为在一些大型的应用中,总会有一些子类去继承另一些父类,如果从父类继承过来却没有具体重写实现,这样调用的就是父类中的这些方法,父类这些方法便给出了友好的提示。这也是抽象类的一个作用,即定义一个产品族,并声明一些必备的方法,如果子类没有重写就会抛出错误。
抽象工厂

//抽象工厂方法
var VehicleFactory = function (subType, superType) {
    //判断抽象工厂中是否有该抽象类
    if (typeof VehicleFactory[superType] === 'function') {
        //缓存类
        function F() { };
        //继承父类属性和方法
        F.prototype = new VehicleFactory[superType]();
        //将子类constructor指向子类
        subType.constructor = subType;
        //子类原型复制父类的一个实例
        subType.prototype = new F();
    } else {
        //不存在该抽象类抛出错误
        throw new Error('未创建该抽象类')
    }
}

在上面的例子中,抽象工厂其实是一个实现子类继承父类的方法,在这个方法中我们需要通过传递子类以及要继承父类(抽象类)的名称,并且在抽象工厂方法中又增加一次对抽象类存在的判断。然后子类通过寄生式继承,继承父类的过程中有一个地方需要注意subType.prototype = new F(),就是在对过渡类的原型继承时,我们不是继承父类的原型,而是通过new 关键字复制父类的一个实例,这么做是因为过渡类不仅仅继承父类的原型方法,还要继承父类的属性,所以需要通过new来将父类的构造函数执行一遍来复制构造函数中的属性和方法。

抽象工厂中添加抽象类也很特殊,因为抽象工厂是个方法不需要实例化对象,故只需要一份,因此直接为抽象工厂添加类的属性,可以通过点语法在抽象工厂上添加需要的抽象类,例如:

//小汽车抽象类
VehicleFactory.Car = function () {
    this.type = 'car'
};
VehicleFactory.Car.prototype = {
    getPrice: function () {
        return new Error('抽象方法不能调用');
    },
    getSpeed: function () {
        return new Error('抽象方法不能调用');
    }
};
//公交车抽象类
VehicleFactory.Bus = function () {
    this.type = 'bus';
};
VehicleFactory.Bus.prototype = {
    getPrice: function () {
        return new Error('抽象方法不能调用');
    },
    getPassengerNum: function () {
        return new Error('抽象方法不能调用');
    }
};
//货车抽象类
VehicleFactory.Truck = function () {
    this.type = 'truck';
};
VehicleFactory.Truck.prototype = {
    getPrice: function () {
        return new Error('抽象方法不能调用');
    },
    getTrainload: function () {
        return new Error('抽象方法不能调用');
    }
}

抽象类的实现,既然抽象工厂是用来创建子类的(本例中其实是让子类继承父类,是对子类的一种拓展),所以我们需要一些产品子类,然后让子类继承相应的产品抽象类,如下:

//宝马汽车类
var BWM = function (price, speed) {
    this.price = price;
    this.speed = speed;
}
//抽象工厂实现对Car抽象类的继承
VehicleFactory(BWM, 'Car');
BWM.prototype = {
    getPrice: function () {
        return this.price;
    },
    getSpeed: function () {
        return this.speed;
    }
}

测试

  console.log(new BWM(10000, 200));//BWM {price: 10000, speed: 200}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值