js-工厂模式

首先需要说一下工厂模式。工厂模式根据抽象程度的不同分为三种

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂模式

1.简单工厂模式

简单工厂模式:又称为静态工厂方法模式,它属于类创建型模式。
在简单工厂模式中,可以根据参数的不同返回不同类的实例。
由工厂对象决定创建某一种产品对象类的实例。

let Ball= function(name){
        let A = new Object();
        A.name = name;
        A.play = function(){
            console.log(`我在打${name}`)
        }
        return A
    }
    let football =  Ball('足球');
    console.log(football)
    football.play(); // 我在打足球
    let basketball =  Ball('篮球');
    basketball.play()  // 我在打篮球

这段案例可以这么去理解,假设我们需要多个球,我们希望在使用球
的时候,只需要告诉管理员我们需要的球的类型,不需要一个个去找对应的球
这个管理员就相对于工厂函数。
简单讲就是使用简单工厂模式,那么你就不需要关心它的具体实现,
你只需要知道你要使用的类型,那么工厂函数会自动帮你去做对应的事情

简单模式的优点

  • 简单讲就是使用简单工厂模式,那么你就不需要关心它的具体实现,
    你只需要知道你要使用的类型,那么工厂函数会自动帮你去做对应的事情。
  • 简单工厂模式最大的优点在于实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责

简单模式的缺点

  • 由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响
  • 使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
  • 工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,而且产品较多时,工厂方法代码将会非常复杂。

2.工厂方法模式

工厂方法模式:又称为工厂模式,也叫虚拟构造器模式或者多态工厂模式
它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对
象的公共接口,而工厂子类则负责生成具体的产品对象,
这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,
即通过工厂子类来确定究竟应该实例化哪一个具体产品类

 let UserFactory = function(role) {
  if(this instanceof UserFactory) {
    var s = new this[role]();
    return s;
  } else {
    return new UserFactory(role);
  }
}

//工厂方法函数的原型中设置所有对象的构造函数
UserFactory.prototype = {
  SuperAdmin: function() {
    this.name = "超级管理员",
    this.viewPage = ['首页', '通讯录', '发现页', '应用数据', '权限管理']
  },
  Admin: function() {
    this.name = "管理员",
    this.viewPage = ['首页', '通讯录', '发现页', '应用数据']
  },
  NormalUser: function() {
    this.name = '普通用户',
    this.viewPage = ['首页', '通讯录', '发现页']
  }
}

//调用
let superAdmin = UserFactory('SuperAdmin');
let admin = UserFactory('Admin') 
let normalUser = UserFactory('NormalUser')

工厂方法模式的优点

  • 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
  • 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。
  • 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

工厂方法模式的缺点

  • 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
  • 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度

3.抽象工厂模式

抽象工厂其实是一个实现子类继承父类的方法,在这个方法种我我们需要传入子类以及要继承父类的名称.
过渡类的原型继承,不是继承父类的原型,而是通过new 复制一个父类的实例,过渡类不仅仅继承了父类的原型方法,还继承了父类的对象属性.
使用方法

let AccountAbstractFactory = function(subType, superType) {
  //判断抽象工厂中是否有该抽象类
  if(typeof AccountAbstractFactory[superType] === 'function') {
    //缓存类
    function F() {};
    //继承父类属性和方法
    F.prototype = new AccountAbstractFactory[superType] ();
    //将子类的constructor指向子类
    subType.constructor = subType;
    //子类原型继承父类
    subType.prototype = new F();

  } else {
    throw new Error('抽象类不存在!')
  }
}
//微信用户抽象类
AccountAbstractFactory.WechatUser = function() {
  this.type = 'wechat';
}
AccountAbstractFactory.WechatUser.prototype = {
  getName: function() {
    return new Error('抽象方法不能调用');
  }
}
//普通微信用户子类
function UserOfWechat(name) {
  this.name = name;
  this.viewPage = ['首页', '通讯录', '发现页']
}
//抽象工厂实现WechatUser类的继承
AccountAbstractFactory(UserOfWechat, 'WechatUser');
//子类中重写抽象方法
UserOfWechat.prototype.getName = function() {
  return this.name;
}
//实例化微信用户
let wechatUserA = new UserOfWechat('微信小李');
console.log(wechatUserA.getName(), wechatUserA.type); //微信小李 wechat
let wechatUserB = new UserOfWechat('微信小王');
console.log(wechatUserB.getName(), wechatUserB.type); //微信小王 wechat
posted @ 2019-02-19 22:42  我会放电啪啪  阅读(737)  评论(0编辑  收藏  举报