JavaScript设计模式-工厂模式

386 阅读4分钟

工厂模式

创建对象的一种最常用的设计模式 主要分为3种  1)简单工厂模式  2)

工厂方法模式 3)抽象工厂模式

1,简单工厂模式

简单工厂模式是一种创建型模式,适用于创建同一类对象。 假如存在以下需求:编写一系列的弹出框,包括:警告框(alert)、输入框(promt)、确认框(confirm) 简单工厂模式的核心思想就是抽象出一个工厂函数,工厂函数内部通过传入的参数进行判断应该实例化和使用哪些类,使用者在使用时便只需要调用工厂函数即可,如此一来,即使更换了类名,我们也只需要修改工厂函数便可。

            function dialogFactory(type,opts) {
			var o = new Object();

			o.title = opts.title;
			o.show = function() {

			}
			switch (type) {
				case "alert":
					alert()
					break;
				case "conform": 
					break;
			}
			return o;
		}
		new dialogFactory("alert",{
			title: "alert弹窗"
		})

所以在JavaScript中,简单工厂模式有两类创建对象的方法: 1)通过类创建对象 2)通过创建一个新对象,然后包装增强其属性和方法 使用前者的好处在于,如果类之间具有共用的方法,可以通过prototype来实现共用,而后者每次调用创建的都是新的方法,所以不能实现方法的共用。但是两者各有各的好处,具体方式则应该依据具体的业务需求。


2,抽象工厂模式

抽象工厂模式笔记
1.抽象工厂模式创建多个抽象类,创建出的结果是一个类簇(这里是抽象类的集合)
2.抽象工厂中传入的父类是否是抽象工厂方法创建的抽象类进行判断,不是则抛出错误
3.子类通过抽象工厂方法(寄生式继承)继承父类(抽象工厂创建的抽象类)的属性和方法  


 原型式继承

        function inheritobject(o){
            //声明一个过渡函数对象
            function F(){    
            }
            //过渡原型对象继承父对象
            F.prototype=o;
            //返回过渡对象的一个实列,该实例的原型继承了父对象
            return new F();
        }

寄生式继承 继承原型

        /*
         *寄生式继承 继承原型
         * 传递参数subclass 子类
         * 传递参数superclass 父类
         * */
        function inheritPrototype(subclass,superclass){
            //复制一份父类的原型副本保存在变量中
            var p=inheritobject(superclass.prototype);
            //修正因为重写子类原型导致子类的constructor属性被修改
            p.constructor=subclass;
            //设置子类原型
            subclass.prototype=p;
        }

抽象工厂方法

            //抽象工厂方法
            var VehicleFactory=function(subtype,supertype){
                //supertype通过typeof判断是否是抽象工厂模式创建的抽象类
                if(typeof VehicleFactory[supertype] === 'function'){
                    inheritPrototype(subtype,supertype);
                }else{
                    throw new Error('未创建该抽象类');
                }
            }

抽象工厂方法创建抽象类

            VehicleFactory.Car=function(){
                this.type='car';
            }
            
            VehicleFactory.Car.prototype={
                getPrice:function(){
                    return new Error("抽象方法不能调用");
                },
                getSpeed:function(){
                    return new Error("抽象方法不能调用");
                },
                getColor: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.price=price;
                this.speed=speed;
            }
            //抽象工厂实现对Car抽象类 的继承
            VehicleFactory(BMW,'Car');
            BMW.prototype.getPrice = function(){
                return this.price;
            }
            BMW.prototype.getSpeed = function(){
                return this.speed;
            }

var BMWObject = new BMW(100,100);
console.log(BMWObject.getPrice());
console.log(BMWObject.getColor());

工厂方法模式

简单工厂模式虽然能够解决创建同类对象的问题,但是却存在以下问题: 

1)当需要添加新的类时,就需要修改工厂方法,这违背了开闭原则(OCP, 对扩展开放、对源码修改封闭) 

2)不适用创建多类对象 于是,工厂方法模式便是为了解决以上问题的另一种创建型模式

工厂方法模式中,具体对象的创建过程不在工厂方法中进行,而是推迟到子类中进行,如此在添加新的类时就无需修改工厂方法,只需要将子类注册进工厂方法的原型对象中即可。

function Factory(type, options) {
    if (this instance of Factory) {
        return this[type](options)
    }
    return new Factory(type, options)
}
// 具体的创建过程
Factory.prototype.productA = function (options) {
    // 产品A的创建逻辑
}
Factory.prototype.productB = function (options) {
    // 产品B的创建逻辑
}
Factory.prototype.productC = function (options) {
    // 产品C的创建逻辑
}
// ...
所以当我们需要添加新的类时,就只需要挂载在Factory.prototype上即可,无需去修改工厂方法,如此更符合开闭原则。
而在使用时,就只需要:

const pdA = new Factory('productA', options)
const pdB = new Factory('productB', options)
// ...