一、概述
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性
设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样
二、工厂模式
JS出现手动创建对象的原因:避免写大量重复的代码
工厂模式:在软件开发中被经常使用的一种设计模式
instanceof方法用于检测一个实例是否归属一个类
弊端:创建的对象无法确定归属于哪一个类
<script>
function Car(lun1, lun2, lun3, lun4, ability) {
var car = {};
car.lun1 = lun1;
car.lun2 = lun2;
car.lun3 = lun3;
car.lun4 = lun4;
car.ability = ability;
return car;
}
//实例化对象
var car1 = Car('左前轮1', '右前轮1', '左后轮1', '右后轮1', '会跑1');
var car2 = Car('左前轮2', '右前轮2', '左后轮2', '右后轮2', '会跑2');
console.log(car1 instanceof Car);
console.log(car2 instanceof Car);
</script>
三、构造函数模式
构造函数模式和工厂模式的区别:
- 没有显示创建一个对象,而是通过new命令隐式创建一个对象
- 让后让隐式对象来实际执行构造函数,故构造函数中的this指向这个隐式对象
- 通过构造模式创建的对象会明确的指明归属于哪一个类
通过构造函数创建的对象必须使用new命令
习惯上构造函数首字母大写,其余部分采用驼峰命名
弊端:面对公有的,属性相同的公有属性,没办法一次写清,必须每次都给这个属性分配内存
<script>
function Car(lun1, lun2, lun3, lun4, ability) {
this.lun1 = lun1;
this.lun2 = lun2;
this.lun3 = lun3;
this.lun4 = lun4;
this.ability = ability;
}
var car1 = new Car('前左轮1', '前右轮1', '后左轮1', '后右轮1', '能开1');
var car2 = new Car('前左轮2', '前右轮2', '后左轮2', '后右轮2', '能开2');
console.log(car1 instanceof Car);
console.log(car2 instanceof Car);
</script>
四、原型模式
原型模式实际上是通过【原型prototype属性】和【对象的__proto__构成的原型链】
这两大js特性,实现了为一个类的所有实例添加都能访问到的属性和方法的功能。即公有
通过原型模式生成的所有对象的属性和方法都指向了类的原型的属性和方法
弊端:省内存到极致的问题是,面对不同属性值的公有属性时,反而增加了内存的负担
<script>
function Car() {}
Car.prototype.lun1 = '左前轮';
Car.prototype.lun2 = '右前轮';
Car.prototype.lun3 = '左后轮';
Car.prototype.lun4 = '右后轮';
Car.prototype.ability = '上天入地';
var car1 = new Car();
car1.lun1 = '新的轮胎';
var car2 = new Car();
console.log(car1.lun1);
console.log(car2.lun2);
</script>
五、混合模式
弊端:没办法在每一个领域做到完美
<script>
//构造函数模式
function Car(lun1, lun2, lun3, lun4) {
this.lun1 = lun1;
this.lun2 = lun2;
this.lun3 = lun3;
this.lun4 = lun4;
}
//原型模式
Car.prototype.ability = function() {
console.log('爷会飞');
};
var car1 = new Car('左前轮1', '右前轮1', '左后轮1', '右后轮1');
var car2 = new Car('左前轮2', '右前轮2', '左后轮2', '右后轮2');
car1.ability();
car2.ability();
console.log(car1);
console.log(car2);
</script>
六、动态原型模式
其实不难发现动态原型模式和混合模式很相似。这是因为动态原型模式最初设计出来就是为了解决原型模式中所有内容都为公有的问题的。所以动态原型模式和混合模式两者功能类似。
在动态原型模式中,通过判断一个类的initialized属性来判断一个类究竟有没有被实例化过。_initialized属性是每一个类都拥有的私有属性,它仅用来表示类是否被实例化过,是一个boolean类型的可读写属性
懒加载:使用时才加载并占内存空间,如果不使用就相当于不存在
<script>
function Car(lun1, lun2, lun3, lun4) {
this.lun1 = lun1;
this.lun2 = lun2;
this.lun3 = lun3;
this.lun4 = lun4;
if (typeof Car._initialized == 'undefined') {
//原型中的内存仅在调用函数的时候才被占用,如果函数一直没被调用则原型一直不会占有内存
Car.prototype.ability = function() {
console.log('爷会飞');
};
Car._initialized = true;
}
}
var car1 = new Car(['左前轮1', '右前轮1', '左后轮1', '右后轮1']);
var car2 = new Car(['左前轮2', '右前轮2', '左后轮2', '右后轮2']);
</script>