写点什么

蓦然回首,“工厂、构造、原型”设计模式,正在灯火阑珊处

作者:掘金安东尼
  • 2022 年 7 月 30 日
  • 本文字数:2141 字

    阅读完需:约 7 分钟

蓦然回首,“工厂、构造、原型”设计模式,正在灯火阑珊处

很多工友们都说:设计模式根本用不到,然而它其实时刻就在我们身边,像王国维所说:众里寻他千百度,蓦然回首,那人正在灯火阑珊处。


本篇带来你一定熟知的、用于创建对象的三种设计模式:工厂模式、构造函数模式、原型模式;


工厂模式

什么是工厂模式?其实就字面意思,在现实社会生活中,市场通过不同工厂加工成不同的产品。


转化成 JS 代码就是这样的:


// 汽车工厂function carFactory(brand, price, district) {   let o = new Object();   o.brand= brand;   o.price= price;   o.district= district;   o.performance= function() {     console.log(this.brand);   };   return o;}// 生产汽车let car1 = carFactory("Benz", 50, "china");let car2= carFactory("Honda", 30, "usa");
复制代码


// 糖果工厂function candyFactory(name, size, color) {   let o = new Object();   o.name= name;   o.size= size;   o.color= color;   o.performance= function() {     console.log(this.name);   };   return o;}// 生产糖果let candy1= candyFactory("Oreo", "small", "white");let candy2= candyFactory("quduoduo", "middle", "black");
复制代码


有汽车工厂,糖果工厂等等,我们通过工厂函数,创建了特定对象。


工厂模式是一种众所周知的设计模式,广泛应用于软件工程领域,用于抽象创建特定对象的过程。

构造函数模式

构造函数是用于创建特定类型对象的,可以自定义构造函数,以函数的形式为自己的对象类型定义属性和方法。


比如前面的例子,就可以该写为:


// 构造汽车的构造函数function Car(brand, price, district) {   this.brand= brand;   this.price= price;   this.district= district;   this.performance= function() {     console.log(this.brand);   };}// 构造汽车let car1 = new Car("Benz", 50, "china");let car2= new Car("Honda", 30, "usa");
复制代码


与工厂模式的区别是,构造函数模式:


  1. 没有显式地创建对象;

  2. 属性和方法直接赋值给了 this;

  3. 没有 return;


构造函数首字母通常是大写;


这里涉及到一个重要的考点:即使用 new 会发生什么?


官方解答:


(1) 在内存中创建一个新对象。 (2) 这个新对象内部的[[Prototype]](隐式原型)特性被赋值为构造函数的 prototype (显示原型)属性。 (3) 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)。 (4) 执行构造函数内部的代码(给新对象添加属性)。 (5) 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。


这个,就是“原型链”的构造过程!!


car1.__proto__===Car.prototype // true
car1 instanceof Car // true
复制代码


  • 构造函数的问题


构造函数的主要问题在于,其定义的方法会在每个实例上都创建一遍。


什么意思?用代码来解释:


// 构造汽车的构造函数function Car(brand, price, district) {   this.brand= brand;   this.price= price;   this.district= district;   this.performance= function() {
};}// 构造汽车let car1 = new Car("Benz", 50, "china");let car2= new Car("Honda", 30, "usa");
car1.performance == car2.performance // false
复制代码


即使是同样的方法,也不相等,因为每次执行 new 的时候,实例的方法都是重新创建的;

原型模式

原型模式可以解决构造函数模式“重复创建方法”的问题。


// 原型创建function Car(brand, price, district) {   Car.prototype.brand= brand;   Car.prototype.price= price;   Car.prototype.district= district;   Car.prototype.performance= function() {
};}
let car1 = new Car("Benz", 50, "china");let car2= new Car("Honda", 30, "usa");
car1.performance === car2.performance // true
复制代码


这里不妨再重温一下原型链的指向关系:


car1.__proto__===Car.prototype // true
Car.__proto__===Function.prototype // true
Function.prototype.__proto__===Object.prototype //true
Car.prototype.__proto__===Object.prototype //true
Object.prototype.__proto__===null // true
复制代码


原型模式弱化了向构造函数传递初始化参数的能力,会导致所有实例默认都取得相同的属性值。


function Person() {}Person.prototype = { constructor: Person, friends: "A", sayName() { }}; let person1 = new Person();let person2 = new Person();person1.friends="B";
person1.friends // 'B'person2.friends // 'A'
复制代码


function PersonArr() {}PersonArr.prototype = { constructor: PersonArr, friends:["A"], sayName() { }}; let person1 = new PersonArr();let person2 = new PersonArr();person1.friends.push("B");
person1.friends // ["A","B"]person2.friends // ["A","B"]
复制代码


原型上的所有属性是在实例间共享的,这对函数来说比较合适。对原始值的属性 也还好,但对于引用值的属性,则会产生混乱!!


小结:


工厂模式、构造函数模式、原型模式,这三者没有谁好谁坏,使用时,更多的是讲究一个 —— 适合!只有清楚它们的原理,才能游刃有余。


OK,以上便是本篇分享。点赞关注评论,为好文助力👍

我是掘金安东尼 🤠 100 万阅读量人气前端技术博主 💥 INFP 写作人格坚持 1000 日更文 ✍ 陪你一起度过漫长岁月 🌏

发布于: 刚刚阅读数: 3
用户头像

还未添加个人签名 2022.07.14 加入

社会我瓜哥,人狠话不多😎 微信 anthony1453,加我交个朋友😎 正联合【机械工业出版社】出版《程序员成长手册》,敬请期待😎 真正的大师,永远怀着一颗学徒的心(易)😎

评论

发布
暂无评论
蓦然回首,“工厂、构造、原型”设计模式,正在灯火阑珊处_JavaScript_掘金安东尼_InfoQ写作社区