简单工厂

对于有许多的不同功能的方法时,又想将其变得共用,这时候简单工厂模式就发挥了重大作用

const Dog = function () { this.species = "犬科";this.name = "孙子"};const Cat = function () {this.species = "猫科";this.name = "小强"}// 简单工厂模式const animateFactory = function (name) { switch (name) { case "Dog":return new Dog();case "Cat":return new Cat();default:return null;}}const dog = animateFactory("Dog") // { species: '犬科', name: '孙子' }const cat = animateFactory("Cat") // { species: '猫科', name: '小强' }

安全模式

首先,我们需要保证一个函数的安全,比如

1、不安全

const Fun = function (name) {this.name = namethis.showName = function(){return this.name}}const fun = new Fun("方人智")console.log(fun.showName()) // 方人智// 但是当我们可能忽略 new 关键字时,问题就出来了const fun1 = Fun("陈歪嘴") // Cannot set properties of undefinedconsole.log(fun1.getName())// 这里就不能调用这个方法

这时,我们可以这样来改造下这个方法,使其变得安全

2、安全改进

const Fun = function (name) {// 在这里做一个判断,当 this 不是 Fun 的实例时,我们帮他 new 一下if (!(this instanceof Fun)) { return new Fun(name);}this.name = namethis.showName = function(){return this.name}}const fun1 = Fun("陈歪嘴")console.log(fun1.showName()) // 陈歪嘴

安全工厂

实际上只是将安全模式给添加到工厂模式中而已

// 安全的工厂函数const SuperFactory = function (type, content) {if (this instanceof SuperFactory) {return new this[type](content)} else {return new SuperFactory(type, content)}}SuperFactory.prototype = {Dog: function (name) {// todo:this.name = name},Cat: function (name) {// todo:this.name = name}}const dog = SuperFactory("Dog", "汪汪")const cat = new SuperFactory("Cat", "喵喵")console.log(dog.name) // 汪汪console.log(cat.name) // 喵喵

抽象工厂

抽象,也就是子类必须要重写父类中的方法才能调用,而不能直接调用父类中的抽象方法,这里面我们在定义工厂基类时使用寄生方式

const VehicleFactory = function (type, superType) {if (typeof VehicleFactory[superType] === "function") {function F() { }F.prototype = new VehicleFactory[superType]()type.constructor = typetype.prototype = new F()}}VehicleFactory.Dog = function () {this.type = "dog"}VehicleFactory.Dog.prototype = {getName: function () {return new Error('抽象方法不能被调用')},getType: function () {return new Error('抽象方法不能被调用')}}VehicleFactory.Cat = function () {this.type = "cat"}VehicleFactory.Cat.prototype = {getName: function () {return new Error('抽象方法不能被调用')}}const Dog = function (name) {this.name = name;}VehicleFactory(Dog, "Dog")Dog.prototype.getName = function () {return this.name;}Dog.prototype.sound = function () {return "汪汪汪"}const Cat = function (name) {this.name = name;}VehicleFactory(Cat, "Cat")Cat.prototype.getName = function () {return this.name;}const dog = new Dog("旺财");const cat = new Cat("Tom");console.log(cat.getName()); // Tomconsole.log(dog.getName()); // 旺财console.log(dog.sound()); // 汪汪汪console.log(dog.getType()); // Error: 抽象方法不能被调用