面向对象的几种设计模式

1.面向对象的概念

其实面向对象是相对于面向过程而言,通俗来说就是创建对象,每个对象有自身的属性和方法,对象.属性  对象.方法 实际上这已经是一个面向对象的过程了,面向过程,是指执行一件事的流程,一步接着一步进行,举个例子来说,比如你去烧菜,面向过程的执行就是,你先要去买菜,然后你要去洗菜,然后烧菜等一系列具体的步骤,而对于面向对象而言,把你当做一个对象,买菜是一个对象,烧菜也是一个对象,你首先会传递消息,你要用菜,菜才就会出现,至于菜是怎么来的,买的还是偷得,那就不需要你知道.......等你洗好会菜会发送消息表明现在要烧菜,菜就会烧好,至于菜是如何烧的,过程如何,你也不需要知道,其实面向过程会细究每一步的执行过程,而面向对象不会细究。

----例子有点不恰当,面向对象的概念本身十分的抽象,只能慢慢体会

2 面向对象的设计模式

一.普通模式

   普通模式比较繁琐,一个对象一个实例,

       普通创建对象的方法,缺陷:

  • 如果创建多个对象会比较繁琐,效率低
  • 实例与原型之间,没有任何办法,可以看出有什么联系。
例如:
      var  people=new Object();
    people.name="张三";
    peoole.food="苹果";
    people.eat=function(){
    alert(this.name+"喜欢吃"+this.food)
    }
       people.eat())//张三喜欢吃苹果
  var  people1=new Object();
    people1.name="李四";
    peoole1.food="香蕉";
    people1.eat=function(){
    alert(this.name+"喜欢吃"+this.food)
    }
      people1.eat()//李四喜欢吃香蕉
//若有100个对象,则需要创建100次,不利于实际的开发

二 工厂模式

这种模式比较简单,其实就是在函数中创建一个对象,给对象添加属性及其属性值或属性方法然后在讲这个对象用return返回出来(return 是关键)

  • 创建过程类似于工厂生产产品的过程,即:原材料--加工--产品...
  • 解决了多次重复创建多个对象的麻烦。
  • 问题:
    • 创建出的实例之间没有内在的联系,不能反映出它们是同一个原型对象的实例。
    • 创建对象的时候没有使用 new 关键字
    • 会造成资源浪费,因为每生成一个实例,都增加一个重复的内容,多占用一些内存。
function create(name,food){
    var people=new Object()   //原材料;
    people.name=nane
    people.food=food
    people.eat=function(){
     alert(this.name+"喜欢吃"+this.food)
  }//加工过程
  return people;//产品
}
var people 1=create("小丸子",“海鲜”);//不用new关键字创建
var people2=create("小李","红烧肉");
     people1.eat()
     people2.eat()
//这种模式的缺点就是内存消耗大
people1==people2   //false,占用不同的内存空间

注意:上面提到一定工厂模式一定要有返回值

如果没有返回,则返回错误如下

三. 构造函数模式

  1. new 调用的函数为构造函数,构造函数和普通函数区别仅仅在于是否使用了new来调用。
  2. 所谓“构造函数”,就是专门用来生成“对象”的函数。它提供模板,作为对象的基本结构。
  3. 构造函数内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。
  4. instanceof 验证原型对象与实例对象之间的关系。
  5. 使用call和apply方法实现对象的冒充
  6. 问题:浪费内存--使用构造函数每生成一个实例,都增加一个重复的内容,多占用一些内存。这样既不环保,也缺乏效率

       new关键字能改变this的作用域

     关键采用this关键字,对于this的理解,见ttps://www.cnblogs.com/yanhaijing/p/3685309.html(比较厉害的大牛)

    function  People(name,food){ //构造函数名首字母要大写,小写不会错,但习惯大写
 this.name=name ;
         this.food=food;
         this.eat=function(){
         alert(this.name+"喜欢吃"+this.food)//此处this指的是windows对象
     }
   }  
  var people1=new people("张三","苹果");
  var people2=new people("李四","香蕉");
  people1.eat()
people1==people2   //false  占用不同的内存空间

小总结:首先函数名首字母应该大写

              与工厂模式不同的是,不需要在函数内部使用关键字new,两者相同的是都消耗很多内存

              new关键字会改变this的作用域。this为当前调用的对象

              创建完成构造函数后需要new一个实例化的对象赋值给一个变量,然后可以通过这个变量来调用构造函数里面的属性以及方法

           构造函数模式可以传递参数

四 原型构造模式

构造函数都会有一个prototype(原型)属性,这个属性其实就是一个指针,它指向了一个对象,在这个对象里包含了可以共享给实例化对象的所有属性及方法

1.第一种写法

   function People(){} //定义一个空函数
  People.prototype.name="张三"; 
  People.prototype.food="葡萄";
  People.prototype.eat=function(){
        alert(this.name+"喜欢吃"+this.food)
  }   //利用prototype属性来添加属性值和方法
  var people1=new People();//创建实例化对象
      var people2=new People();
     people1.eat();
  people1.eat==people2.eat  //true;  判断是否是相同内存
    alert(people1.constructor)  //返回构造函数

2 第二种写法

  function People(){}
  People.prototype={
    name:"小米",
    food:" 火锅",
         job  :["IT","销售"],
    eat:function(){
        alert(this.name+"喜欢吃"+this.food)
      }
  }
  var people1=new People();
         people1.job.push("金融");
         var people2=new People();
         people2.job.push("服务");
            alert(people1.job)   //弹出为 IT ,销售,金融,服务
            alert(people2.job)   //弹出为 IT ,销售,金融,服务(由于两者地址相同,所以无论哪一方在向数组中添加,都会全部显示出来)

小总结:原型模式过于呆板,内容定义只能唯一,如果改变其中的属性值,则全部都会改变,没有使用this活泼,内存如果想修改其中一个实例化对象的属性或方法另一个实例对象也会随改变,这并非我们想要的结果,所以就会诞生了混合模式。

补充:

  1. prototype方式定义的方式,函数不会拷贝到每一个实例中,所有的实例共享prototype中的定义,节省了内存。
  2. Prototype模式的验证方法
    1. isPrototypeOf()这个方法用来判断,某个proptotype对象和某个实例之间的关系。
    2. hasOwnProperty()每个实例对象都有一个hasOwnProperty()方法,用来判断某一个属性到底是本地属性,还是继承自prototype对象的属性。
    3. in运算符in运算符可以用来判断,某个实例是否含有某个属性,不管是不是本地属性。in运算符还可以用来遍历某个对象的所有属性。
  3. 对象的constructor属性用于返回创建该对象的构造函数.
  4. 原型方式的问题:
    • 构造函数没有参数。使用原型方式,不能通过给构造函数传递参数来初始化属性的值
    • 属性指向的是对象,而不是函数时。函数共享不会造成问题,但对象却很少被多个实例共享,如果共享的是对象就会造成问题

五 混合模式(构造函数模式+原型模式)

//构造函数模式可以传递参数,而且使用this关键字,活动性很强,但消耗内存过多

//原型模式消耗内存小,但活动性很差,因此两者合并,当需要传递参数时,则使用构造函数,当需要执行方法时,使用原型模式,

这是目前最为常用的创建对象的方式。

这种概念非常简单,即用构造函数定义对象的所有非函数属性,用原型方式定义对象的函数属性(方法)。结果是,所有函数都只创建一次,而每个对象都具有自己的对象属性实例。

此外,组合模式还支持向构造函数传递参数,可谓是集两家之所长。

在所接触的JS库中,jQuery类型的封装就是使用组合模式来实例的!!!

  function  People(name,food){
  this.name=name;
  this.food=food;
  }
  People.prototype={
  eat:function(){
     alert(this.name+"喜欢吃"+this.food)
    }
  }
  var people1=new People("小明","鸡蛋");
  var people2=new People(“张三”,“水饺”)
  people1.eat();
  people2.eat();
 people1.eat==people2.eat   //true  (eat属性属于原型模式,内存相同)
people1.name==people2.name  //flase (name属于构造函数属性,内存不同)

六 动态模式

   function People(name,food){
		  this.name=name;
		  this.food=food;
		  if(typeof this.eat!='function'){
			     alert("程序开始");
			  People.prototype.eat=function(){
				     alert(this.name+"喜欢吃"+this.food)
			  }
		}

	}
	    var people1=new People("小明","鸡蛋");
	    var people2=new People("小红","饺子");
	       people1.eat()
	       people2.eat();

//执行结果图:

有执行结果图看出动态模式更好的让我们避免创建对象多次初始化

详细代码见:(明天上传github)

有理解不正确的地方,希望大神们指点!

 我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1v9cvnavta0pn

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏take time, save time

初级程序员面试不靠谱指南(二)

3.read-only的const。如果你突然冒出一句看似很高深的话但又不解释一般都是装逼,就像前面提到过const准确的应该理解为一个read-only的变量...

2907
来自专栏工科狗和生物喵

【计算机本科补全计划】C++ Primer:指针和const限定符

正文之前 今天下午看了一下午的计算机组成与设计,结果好死不死的看到了设计部分--处理器的设计。天哪,我现在还只是一个准备给人装一台电脑做实验田的家伙,连用都不咋...

2794
来自专栏Java Web

Java学习笔记(2)——数据类型

终于要写点干货了,其实思考了很久下面一篇文章要写什么,主要的纠结点在于,既想要分享那些精美的知识,又怕这些知识不太好嚼。后来想想还是对初学者不太好友算了..一...

2723
来自专栏noteless

[五]java函数式编程归约reduce概念原理 stream reduce方法详解 reduce三个参数的reduce方法如何使用

java8 流相关的操作中,我们把它理解 "累加器",之所以加引号是因为他并不仅仅是加法

2933
来自专栏喵了个咪的博客空间

zephir-(10)内置函数

#zephir-内置函数# ? ##前言## 先在这里感谢各位zephir开源技术提供者 嗨!大家好呀,今天要和大家一同学习zephir的内置函数,学过PHP的...

3658
来自专栏鸿的学习笔记

Python和Scala的定义变量

每一门的编程语言背后都代表着某一种特别的哲学,由这一哲学进而设计出属于这门程序语言的语法,Python和Scala也不例外。我们从变量的定义去一窥Python和...

942
来自专栏北京马哥教育

Python入门学习篇(10)-循环语句

当我们需要执行一个语句或者语句组多次,不可能将同样的语句写多遍,一是比较繁琐, 二是不利于维护,这时候循环语句就应运而生。下面是在大多数编程语言中的循环语句的一...

990
来自专栏java一日一条

Java中有关Null的9件事

对于Java程序员来说,null是令人头痛的东西。时常会受到空指针异常(NPE)的骚扰。连Java的发明者都承认这是他的一项巨大失误。Java为 什么要保留nu...

932
来自专栏大数据钻研

让你分分钟学会 javascript 闭包

闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它。...

2764
来自专栏云飞学编程

Python学习,这些高阶函数和高阶特性值得一学

Python语言这么火,不论是对于刚开始学习的编程小白或者有接触过其他语言(c/c++/java等等)的同学来说,写代码的时候难免会受本身惯性思维或者其他语言的...

973

扫码关注云+社区

领取腾讯云代金券