简单工厂
对于有许多的不同功能的方法时,又想将其变得共用,这时候简单工厂模式就发挥了重大作用
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 = name
this.showName = function(){
return this.name
}
}
const fun = new Fun("方人智")
console.log(fun.showName()) // 方人智
// 但是当我们可能忽略 new 关键字时,问题就出来了
const fun1 = Fun("陈歪嘴") // Cannot set properties of undefined
console.log(fun1.getName()) // 这里就不能调用这个方法
这时,我们可以这样来改造下这个方法,使其变得安全
2、安全改进
const Fun = function (name) {
// 在这里做一个判断,当 this 不是 Fun 的实例时,我们帮他 new 一下
if (!(this instanceof Fun)) {
return new Fun(name);
}
this.name = name
this.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 = type
type.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()); // Tom
console.log(dog.getName()); // 旺财
console.log(dog.sound()); // 汪汪汪
console.log(dog.getType()); // Error: 抽象方法不能被调用