对于我这种半路出家自学的前端,设计模式在平时工作中可能用到,但是由于完全不了解,并不会深入思考,以至于开发新项目时完全不会考虑到如何整体架构,直接cv一把梭;路漫漫其修远兮,慢慢补上吧;
设计模式大致可以分为三大类
- 创建性设计模式–解决创建对象时候的问题
- 结构性设计模式–解决对象和类组合在一起时候的问题
- 行为性设计模式–解决对象和类耦合,职责之间的问题
概念就不罗嗦了,百度一下各处描述大都一致
今天要写的工厂模式就属于三大类里的创建型设计模式
假设想要创建一个对象,对象属性包括姓名,年龄,行为;
如果使用变量去描述
let name = 'dahuang';
let age = '3';
let saySth = function(){console.log('woof')}
这是定义一个对象,如果要创建更多对象,则会声明大量变量代码冗余,占用内存难以管理
更好的方式是使用对象去创建;
let dahuang = {
name = 'dahuang';
age = '3';
saySth = function(){console.log('woof')}
}
相对变量会好一些,各个变量和对象之间相互关联,但是仍没有解决创建多个包含同类属性的对象结构冗余的问题
function Animal(){
return{
name = 'dahuang';
age = '3';
saySth = function(){console.log('woof')}
}
}
如上所示,可以说就是一个工厂的雏形了,就可以基本满足需求,问题是属性是常量,创建多个对象值是不会变的,很明显这没法用
function Animal(name,age,sth){
return{
name = name;
age = age;
saySth = function(){console.log(sth)}
}
}
let cat = Animal('dahuang',3,'woof');
let dog = Animal('mimi',4,'mew')
用一个函数描述一个对象,避免重复去声明属性,这就完成了一个简单工厂
工厂模式解决了代码冗余的问题,但是普通函数一般用来封装指定功能,还是不能看出构造函数和实例之间的关系/instanceof
使用构造函数
function Animal(name,age,sth){
this.name = name;
this.age = age;
this.saySth = function(){console.log(sth)}
}
//用class也是一样的
class Animal {
constructor(name, age, sth) {
this.name = name;
this.age = age;
this.sth = sth;
}
saySth() {
console.log(this.sth)
}
}
上面工厂方式创建的实例化对象,共享工厂函数中的属性和方法,但是如果想要给实例化对象不同的属性方法呢
寄生增强方式
function AnimalPlus(){
let animal = new Animal('dahuang',3,'woof');
animal.getSth = function(){
return sth
}
return animal
}
随之而来的问题就是,实例化的对象又变成同一个了,继续改造
function AnimalPlus(name, age, sth){
let animal = new Animal(name, age, sth);
animal.getSth = function(){
return sth
}
return animal
}
现在吧需求搞的再极端一些,可能我们不满足与添加一两个属性,而是有很大区别逐个去添加就很麻烦,干脆直接去定义多个类,工厂还不能丢,emmm…;下面就是工厂方法模式亮相
let Animal = (function () {
let _class = {
Cat(obj) {
this.name = obj.name;
this.age = obj.age;
return this;
},
Dog(obj) {
this.name = obj.name;
this.age = obj.age;
this.leg = obj.leg
return this;
}
}
return class {
constructor(type, obj) {
if (_class.hasOwnProperty(type)) {
return _class[type].call(this, obj)
} else {
throw new Error(`不存在${type}类`)
}
}
}
})()
let cat = new Animal('Cat', {name:'dahuang', age:3});
let dog = new Animal('Dog', { name:'mimi', age:5,leg:3});
这样需求增加,需要添加新的类时,只需要在_class对象中添加新的实例就完事了,完全不需要修改工厂函数,避免修改过多的代码逻辑。