工厂模式,构造器模式和原型模式的区别_情节的结构模式有哪些

工厂模式,构造器模式和原型模式的区别_情节的结构模式有哪些工厂模式,构造函数模式(寄生构造函数模式,稳妥构造函数模式,作用域安全的构造函数模式),原型模式(动态原型模式)

工厂模式,构造器模式和原型模式"

一、工厂模式

工厂模式属于创建型模式,它提供了一种创建对象的最佳方式。我们在函数内部创建一个对象,赋予对象属性和方法,并通过return返回这个对象

function createPerson(name, age, job) {
    var o = new Object()
    o.name = name
    o.age = age
    o.job = job
    o.sayName = function() {
      console.log(this.name)
    }
    return o
  }
  var person1 = createPerson('caoyuan', 25, 'Software engineer')
  var person2 = createPerson('neil', 23, 'Software engineer')
  console.log(person1) // {name: "caoyuan", age: 25, job: "Software engineer", sayName: ƒ}
  console.log(person2) // {name: "neil", age: 23, job: "Software engineer", sayName: ƒ}

二、构造函数模式

构造模式和工厂模式创建对象的不同点在于;

  1. 没有显式的创建对象
  2. 直接将属性和方法赋值给了this对象
  3. 没有return对象
function Person(name, age, job) {
    this.name = name
    this.age = age
    this.job = job
    this.sayName = function() {
      console.log(this.name)
    }
  }
  let person1 = new Person('caoyuan', 25, 'Software Engineer')
  let person2 = new Person('neil', 23, 'Software engineer')
  person1.sayName()
  person2.sayName()

以这种方式调用构造函数实际会经历一下四个步骤

  1. 创建一个对象
  2. 将构造函数的作用域赋给新对象(因此this就指向这个对象)
  3. 执行构造函数种的代码(为这个新对象添加属性)
  4. 返回对象

寄生构造函模式

这种模式的基本思想是创建一个函数,该函数的作用仅仅是封装对象的代码,然后再返回新创建的对象。

function Person(name, age, job) {
    var o = new Object()
    o.name = name
    o.age = age
    o.job = job
    o.sayName = function() {
      console.log(this.name)
    }
    return o
  }
  let friend = new Person('neil', 25, 'software Engineer')
  friend.sayName() // neil

以上就是例子,把new操作符抛去,这个模式和工厂模式一模一样。构造函数在不返回值的情况下,默认会返回新对象实例,而通过构造函数的末尾添加一个return语句,可以重写调用给构造函数时返回的值。 如下例子

function SpecialArray () {
    // 创建数组
    var values = new Array()
    // 添加值
    values.push.apply(values, arguments)
    // 添加方法
    values.toPipedString = function() {
      return this.join('|')
    }

    // 返回数组
    return values

  }
  var color = new SpecialArray('1','2','3')
  console.log(color.toPipedString()) // 1|2|3

稳妥构造函数模式 稳妥对象是指没有公共属性, 方法也不引用this的对象。适合在安全的环境中,或者防止数据被其他应该改动时使用

稳妥模式遵循与寄生构造函数类似的模式,但 有两点不同;

  1. 创建新对象的实例不引用this;
  2. 不使用new操作符调用构造函数
function Person(name, age, job) {
    var o = new Object()
    o.sayName = function() {
      console.log(name)
    }
    return o
  }

  let person = Person('neil', 25, 'software Engineer')
  person.sayName() // neil

作用域安全的构造函数

通过代码介绍下作用域安全的构造函数
function Person(name, age, job) {
    this.name = name
    this.age = age
    this.job = job
  }
 var person = Person('neil', 25, 'Softwate Engineer')
 console.log(window.age) // 25

假设用上述这种方式调用,this指向window,那么值也就在window上了,那么怎么才能解决这种问题呢, 修改代码如下

function Person(name, age, job) {
    if (this instanceof Person) {
      this.name = name
      this.age = age
      this.job = job
    } else {
      return new Person(name, age, job)
    }
  }
  var person = Person('neil', 25, 'software Engineer')
  console.log(window.age) // undefined
  console.log(person.age) // 25

通过instanceof来判断当前this是否是person实例上的,现在看上去好像没有什么问题了,那么假设用了构造函数窃取模式的继承且不使用原型链,这个继承可能就被破坏了

function Polygon(sides) {
    if (this instanceof Polygon) {
      this.sides = sides
      this.getArea = function() {
        return 0
      }
    } else {
      return new Polygon(sides)
    }
  }

  function Rectangle(width, heigth) {
    Polygon.call(this, 2) 
    this.width = width
    this.heigth = heigth
    this.getArea = function () {
      return this.width * this.heigth
    }
  }
  let rect = new Rectangle(5, 10)
  console.log(rect.sides) // undefined

你会发现,rect.sides为undefined,为啥呢,Polygon这个实例是安全的,但是,Rectangle中是通过call来继承Polygon的sides属性,这是因为this对象不是Polygon的实例,所以创建了一个新的Polygon对象,Rectangle中并没有sides属性。如果构造函数窃取结合使用原型链和寄生模式就可以解决这个问题了,代码如下

function Polygon(sides) {
    if (this instanceof Polygon) {
      this.sides = sides
      this.getArea = function() {
        return 0
      }
    } else {
      return new Polygon(sides)
    }
  }

  function Rectangle(width, heigth) {
    Polygon.call(this, 2) 
    this.width = width
    this.heigth = heigth
    this.getArea = function () {
      return this.width * this.heigth
    }
  }
  Rectangle.prototype = new Polygon()
  let rect = new Rectangle(5, 10)
  console.log(rect.sides) // 2

三、原型模式

我们创建的每个函数都有prototype属性,这个属性是一个指针,指向对象,而这个对象包含可以由特定类型的所有实列共享的属性和方法。prototype就是通过调用构造函数而创建的那个实例对象的原型对象。

  function Person() {
  }
  Person.prototype.name = 'caoyuan'
  Person.prototype.age = '25'
  Person.prototype.sayName = function() {
    console.log(this.name)
  }
  let person1 = new Person()
  let person2 = new Person()
  person2.sayName()
  person1.sayName()
  console.log(person1.sayName == person2.sayName)

动态原型模式

它把所有信息都封装在了构造函数中,而通过在构造函数中初始化原型,也保持了同时使用构造函数和原型的优点

function Person(name, age, job) {
    this.name = name
    this.age = age
    this.job = job
    // 方法
    if (typeof this.sayName != 'function') {
      Person.prototype.sayName = function() {
        console.log(this.name)
      }
    }
  }
  let person = new Person('neil', 25, 'Software Engineer')
  person.sayName()

四、组合使用构造函数模式和原型模式

创建自定义对象最常见的方式,就是组合使用构造函数模式和原型模式。

  1. 构造函数模式定义实例的属性
  2. 原型模式用于定义方法和共享的属性
function Person(name, age, job) {
  this.name = name
  this.age = age
  this.children = ['1', '2']
}
Person.prototype.sayName = function() {
  console.log(this.name)
}

let person1 = new Person('caoyuan', 25, 'Software Engineer')
let person2 = new Person('neil', 23, 'Software Engineer')

person1.children.push('3')
console.log(person1.children) // Array [1,2,3]
console.log(person2.children) // Array [1,2]
console.log(person1.children === person2.children) // false
console.log(person1.sayName === person2.sayName) // true

相关文章:

原型链基础及多种使用方式

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13896.html

(0)

相关推荐

  • 无任何编程基础的人,该怎么入门编程语言_编程需要什么基础

    无任何编程基础的人,该怎么入门编程语言_编程需要什么基础拿我自己来说吧,作为一个入行8年的老程序员,我不是科班生,完全是从零基础自学的编程,刚开始的时候也遇到了很多问题,跌过不少跟头,好在一路坚持了下

    2022-12-14
    281
  • 计算机编程中的0的平方根

    计算机编程中的0的平方根在数学上,我们知道任何正数的平方根都是一个非负数,两个相同的负数平方所得到的的结果相同,但我们无法通过算术方式得到0的平方根。在编程中,0的平方根表现为一个特殊的NaN(Not a Number)值,表示不是一个数字。

    2024-03-01
    87
  • Mysql实战45讲-[通俗易懂]

    Mysql实战45讲-[通俗易懂]即使是一个开发工程师,也只是 MySQL 的用户,但在了解了一个个系统模块的原理后,再来使用它,感觉是完全不一样的。 当在代码里写下一行数据库命令的时候,就能想到它在数据库端将怎么执行,它的性能是怎么

    2023-02-12
    145
  • 一行代码解决缓存击穿问题「建议收藏」

    一行代码解决缓存击穿问题「建议收藏」重新回顾一下缓存击穿这个问题! 因为目前网上流传的文章落地性太差(什么布隆过滤器啊,布谷过滤器啊,嗯,你们懂的),其实这类方案并不适合在项目中直接落地,本文提供的是真正简便方案。

    2023-08-06
    129
  • 前端通过定时器自定义双击dblclick事件

    前端通过定时器自定义双击dblclick事件
    前端通过定时器自定义双击dblclick事件 1.绑定事件 @click=”handleGroupClick(item)” 2.定义变量 let time …

    2023-04-06
    155
  • MySQL数据库中的数据类型与Java中对应记忆_请列举MySQL中常见的数据类型

    MySQL数据库中的数据类型与Java中对应记忆_请列举MySQL中常见的数据类型整数类型 标准 SQL 中支持 INTEGER 和 SMALLINT 这两种类型,MySQL 数据库除了支持这两种类型以外,还扩展支持了 TINYINT、MEDIUMINT 和 BIGINT 整数类型

    2023-05-12
    144
  • 使用Python储存数据值的示例

    使用Python储存数据值的示例Python作为一门高级编程语言,提供了很多处理数据的便捷方法。在Python中,可以使用各种数据类型来储存数据。最常见的数据类型包括整数、浮点数、字符串和布尔值。对于复杂的数据类型,比如列表、元组、集合和字典等,Python也提供了丰富的内置方法来操作。

    2024-03-01
    154
  • Redis(一)安装[通俗易懂]

    Redis(一)安装[通俗易懂]Redis(一)安装 我使用的是Centos8.1和redis6.2.6 Redis的官方网站地址:https://redis.io/ 1.安装gcc依赖 在root用户下执行 yum install

    2023-06-17
    161

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注