JavaScript中的设计模式——工厂模式
- 在我们的项目开发中会定义很多的类,当协作开发时,每个人都有可能定义很多的类,若是不对每个人或者每一种类进行管理的话,开发中对类的使用将会极其困难,而工厂模式就是对类进行管理的一种模式
- 工厂模式一般有以下几种,分别对应不同的使用场景
简易工厂模式
- 简易工厂模式:不去关心子类的创建过程,只是提供一个函数向外提供他们想要的子类即可
- 该模式就是单纯的对同一类型的类进行管理,使用者只需要传入每一个类的别名或简称即可获取该类
function LoginClass(){
console.log('我是登录模块类')
}
function RegisterClass(){
console.log('我是注册模块类')
}
function LogoutClass(){
console.log('我是退出登录模块类')
}
function createUserClass(name){
switch(name) {
case 'login':
return new LoginClass()
case 'register':
return new RegisterClass()
case 'logout':
return new LogoutClass()
}
}
let login = createUserClass('login')
let register = createUserClass('register')
let logout = createUserClass('logout')
- 上面就是一个简易的工厂模式,一般用于管理同类型的类,对外提供每个类型的别名即可使用
工厂模式
- 工厂模式:工厂模式一般用于会不断创建新类时使用,比如我初始提供了三个类,突然需求变化新增了一个类,如果还使用建议工厂模式的话就需要先创建这个新类,然后在对外暴露的函数中再加一条case语句,会比较繁琐,所以就产生了工厂模式
- 工厂模式是对一个工厂类的拓展,在该类的原型对象上面绑定工厂内所能提供的子类,调用者通过传入不同的类名可获取相应的实例
- 工厂模式由于对外提供的是一个工厂类,若是项目新成员或者不熟悉开发的成员在调用过程中将其当做普通函数处理可能会出现异常并且会在全局对象上挂载太多全局变量,所以我们这里要对工厂类进行安全模式
function Factory(name){
if(this instanceof Factory) {
return new Factory[name]()
} else {
return new Factory(name)
}
}
- 上面就是对工厂类的安全模式,可防止意外调用导致的一系列问题
- 对安全模式的工厂类进行原型对象绑定即可实现我们最终的工厂模式,按需创建类,按需获取类
function Factory(name){
if(this instanceof Factory) {
return new this[name]()
} else {
return new Factory(name)
}
}
Factory.prototype = {
JS: function(){
this.name = 'js'
},
PHP: function(){
this.name = 'php'
this.age = 16
this.say = function(){
console.log('php是世界上最好的语言')
}
},
JAVA: function(){
this.name = 'java'
this.advantage = '我是最稳定的'
this.say = function(){
console.log(this.advantage)
}
}
}
var js = new Factory('JS')
var php = Factory('PHP')
var java = new Factory('JAVA')
php.say()
java.say()
- 上面就是最终的工厂模式,可以看到,当我们需要添加新类的时候只需要在工厂类的原型对象上添加即可,添加完成便可以在别的地方传入名称直接由工厂类生成,需求变化也只需要修改一个地方即可
抽象类
- 了解抽象工厂类之前我们需要先了解抽象类,抽象类就是只能继承,无法实例化的一种类,实例化时会抛出异常,且继承抽象类的子类必须重写抽象类的方法。js中abstract仍然只是一个保留字,并没有实现抽象类,所以抽象类需要我们模拟实现
- 抽象类在实现上与普通类相似,只是对其方法进行了限制,下面的Car就是一个抽象类
let Car = function(){
this.name = 'Car'
}
Car.prototype = {
getSpeed: function(){
throw new Error('不可调用抽象方法')
},
getPrice: function(){
throw new Error('不可调用抽象方法')
}
}
抽象工厂类
- 抽象工厂类是对外提供抽象类的工厂模式,下面就是一个抽象工厂模式
function VehicleFactory(SubClass, SuperClass){
if(typeof VehicleFactory[SuperClass] === 'function'){
function F(){}
F.prototype = new VehicleFactory[SuperClass]()
SubClass.prototype = new F()
SubClass.prototype.constructor = SubClass
} else {
throw new Error('未创建该抽象类')
}
}
VehicleFactory.Car = function(){
this.name = 'Car'
}
VehicleFactory.Car.prototype = {
getSpeed: function(){
throw new Error('不可调用抽象方法')
},
getPrice: function(){
throw new Error('不可调用抽象方法')
}
}
VehicleFactory.Bus = function(){
this.name = 'Bus'
}
VehicleFactory.Bus.prototype = {
getSpeed: function(){
throw new Error('不可调用抽象方法')
},
getPrice: function(){
throw new Error('不可调用抽象方法')
}
}
function BWM(price, speed){
this.price = price
this.speed = speed
}
VehicleFactory(BWM, 'Car')
var b = new BWM(500000, 100)
b.getPrice()
b.getSpeed()
function BRT(price, speed){
this.price = price
this.speed = speed
}
VehicleFactory(BRT, 'Bus')
BRT.prototype.getPrice = function(){
console.log(this.price)
}
BRT.prototype.getSpeed = function(){
console.log(this.speed)
}
var t = new BRT(300000, 80)
t.getPrice()
t.getSpeed()
- 这里我们的抽象工厂可以实现一个实体类对其想要的抽象类的继承,注意点就是要重写抽象类的方法再调用,否则会抛出异常