前端设计模式之工厂模式

148 阅读3分钟

工厂模式

简单工厂模式

说到简单工厂模式,不禁让我想起了早年间的商店,超大玻璃柜台堵住了所有想要揩点油小朋友, 拿着手里面仅有的几分钱,指着柜台里面口馋的把把糖,迫不及待的喊着店主帮忙拿给自己。现 如今,超市替代了小商店,购物从此只能自挑自买,往往有时超市逛了一圈,尽发现该超市并不出 售该物件儿,你说气人不。(当然这里指的是一般情况啦,询问服务员等等的方式另说)

言归正传:所谓简单工厂模式,就好比我去商店买东西,你只需要告诉店家你需要的是什么 东西,要么店家直接那给你,要么就告诉你没有这个物什儿。

举个例子

比如一个商店,现有梨子和苹果两种商品,如果你想要买苹果,只需要告诉店家"苹果",店家就会把 苹果交到你手里,梨子亦是同样的道理,但是现在,你想要买香蕉,你告诉店家"香蕉",店家一看我 店里面并没有你所要的香蕉,就会告诉你"对不起,没有你想要的香蕉"

下面我们以代码的形式来呈现以下

function Pear(){
    this.name = '梨子'
}
function Apple(){
    this.name = '苹果'
}

function simpleFactory(type){
    switch(type){
        case 'apple':
            return new Apple()
        case 'pear':
            return new Pear()
        default:
            return `对不起,没有你想要的${type}`
    }
}
var apple = simpleFactory('apple')
var pear = simpleFactory('pear')
var banana = simpleFactory('banana')
// console.log(apple,pear,banana)    // 苹果    梨子    undefined
console.log('apple',apple)
console.log('pear',pear)
console.log('banana',banana)

工厂方法模式

所谓工厂方法模式,实质上是基于对象去实现的,我们知道javascript当中的函数,既可以当作 函数去使用,也可以当作方法去使用,更能够用于创建对象函数使用

直接调用: 相当于赋值

var result = func()

方法使用:对象的属性指针指向该函数内存地址,当使用时用对象.属性的方式调用

obj.func = func
var result = obj.func()

创建对象:在函数前面使用new关键字,函数本身就会被当作构造函数使用

var result = new func()

言归正传,工厂方法模式就是将多个不同的类型以工厂对象原型属性的方式存放,当使用时只需要 提供不同的参数,调用对应的原型方法便即可,而如果有新的类型到来时,我们也只需要改动一下 工厂对象的原型即可,下面看代码

function FuncFactory(type,content){
    if(!(type in FuncFactory.prototype)){
        return '没找到这个属性'
    }
    if(this instanceof FuncFactory){
        var s = new this[type](content)
        return s
    }else{
        return new FuncFactory(type,content)
    }
}

FuncFactory.prototype={
    Apple:function(msg){
        this.name = `apple------${msg}`
    },
    Banana:function(msg){
        this.name = `banana------${msg}`
    }
}
FuncFactory.prototype.constructor = FuncFactory
var apple = FuncFactory('Apple','100块/斤')
var banana = new FuncFactory('Banana','300块/斤')
console.log(apple,banana)

抽象工厂模型

js里面是没有抽象类,接口等概念,但是在实际开发当中,像接口,抽象类往往为我们提供了很多的便利,例如提心开发人员去实现抽象类里面定义了的抽象方法。而抽象工厂模式,便是在没有抽象类的基础上,提供了我们一种类似抽象类的实现方式 说实在的,这块儿的学习让我感觉非常的拗口,函数两用,属性两用 1. 将函数作为函数使用的同时,又作为对象去使用 var VehicleFactory = function(){} VehicleFactory.Car = function(){} 第一行定义了一个函数,接着便将刚刚定义的函数作为对象去使用 2. 将对象的属性作为属性用的同时,又作为构造函数去使用 VehicleFactory.Car.prototype = {} 将对象的属性作为构造函数,并修改其原型链

var VehicleFactory = function(subType,superType){
    if(typeof VehicleFactory[superType] === 'function'){
        function F() {}
        F.prototype = new VehicleFactory[superType]()
        subType.constructor = subType
        subType.prototype = new F()
    } else {
        throw new Error('未创建该抽象类')
    }
}
// 小汽车抽象类
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('抽象方法不能被调用')
    },
    getSpeed: function(){
        return new Error('抽象方法不能被调用')
    }
}


接着我们看看他的具体实现
var BMW = function(price,speed){
    this.speed = speed
    this.price = price
}
VehicleFactory(BMW,'Car')

var bmw = new BMW(10000000000,200)
console.log(bmw,bmw.getPrice())

接下来我们看一下如果在子类里面实现了抽象类里面的方法,又会是怎样,我想大家已经有了答案
BMW.prototype.getPrice = function(){
    return this.price
}
BMW.prototype.getSpeed = function(){
    return this.speed
}
var bmw2 = new BMW(1223232323,400)
console.log(bmw2,bmw2.getPrice())

github地址: github.com/ypf0088/blo…