2-设计模式-面向对象(学习设计模式的笔记)

598 阅读5分钟

面向对象的概念

面向对象程序设计(OOP)是种具有对象概念的程序编程典范。它可能包含数据、属性、方法对象则指的是的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高代码的重用性灵活性扩展性,对象里的程序可以访问及修改对象相关连的数据。

类与对象

image.png 类是一组相关的属性和行为的集合。类就是对一些具有共性特征,并且行为相似的个体的描述。(比如小李和老张都有姓名、年龄、身高、体重等一些属性,并且两人都能够进行聊天、运动等相似的行为方法。 )

属性,对象所拥有的静态特征在类中的表现被称为类的属性,即事物"拥有"什么

方法,对象执行的操作称为类的方法,即事物"能做"什么

对象是类的实例。是该类事物的具体表现形式,是具体存在的个体。

使用方法:Var 对象名 = new 类名( );

面向过程与面向对象

面向过程是一件事情“该怎么做” ,凡事亲力亲为,每件事的具体过程都要知道,注重过程。

面向对象是一件事情“该让谁做”,根据需求寻找对象,所有的是都用对象来做,注重结果。

解决问题模块

面向过程,函数;

面向对象,对象。

解决问题中心角度

面向过程,How,“如何做?”(流程封装为函数,“如何”就是过程,谁来做仅是参数);

面向对象,Who,“谁来做?”(“谁”就是对象,如何做是他自己的操作,多个对象协同完成任务)。

解决问题步骤角度

面向过程,先具体逻辑细节,后抽象问题整体;

面向对象,先抽象问题整体,后具体逻辑细节。

复用层次角度

面向过程,方法层复用;

面向对象,对象层复用。

具体代码:

// 狗吃屎
//面向过程  ---- > 吃
var name = "";
var age = "";
function eat(params) {
	console.log("旺财正在吃" + params);
}
eat("粑粑");
eat("猪肉");

//面向对象  ---- >  狗
class Dog {
     constructor(name, age, color) {
       this.name = name;
       this.age = age;
       this.color = color;
     }
     eat(food) {
       console.log(
         this.name +
           "是一条大" +
           this.color +
           "狗,今年" +
           this.age +
           "岁,正在吃" +
           food
       );
     }
}
let dahuang = new Dog("大黄", "2", "黄");
let xiaohei = new Dog("小黑", "3", "黑");
dahuang.eat("牛排");
xiaohei.eat("骨头");

再举个例子:

把大象装进冰箱。

面向过程的方法

1、开门(冰箱)

2、装进(冰箱,大象)

3、关门(冰箱)

面向对象的方法

1、冰箱.开门( )

2、冰箱.装进(大象)

3、冰箱.关门( )

由此可以看出:

面向过程是以动词为主,完成一个事件就是将不同的动作函数按顺序调用。

面向对象是以主谓为主,将主谓看成一个个对象,然后对象有自己的属性和方法。如冰箱有自己的id属性,有开门、装东西、关门等方法。然后可以直接调用冰箱的装东西方法并给其传入一个参数大象即可。

面向对象三要素

继承:

继承可以将公共的方法抽离出来,提高复用、减少冗余。子类继承父类。

代码示例:

//父类
      class People {
        constructor(name, age, sex) {
          this.name = name;
          this.age = age;
          this.sex = sex;
        }
        say(message) {
          console.log(message);
        }
      }

//子类 子类继承父类 , 父类的功能 子类可以继承 
      class Child extends People {
        constructor(name, age, sex) {
          super(name, age, sex);
        }
        say(){
            console.log("我会说中文");
        }
        fly() {
          console.log("俺会飞!");
        }
      }
      class Child1 extends People {
        constructor(name, age, sex) {
          super(name, age, sex);
        }
        say(){
            console.log("我会说英文");
        }
        fly() {
          console.log("俺会飞!");
        }
      }


      let zhangsan = new child();
      zhangsan.say("都是石头里面蹦出来的,为啥他是猴子!");
      zhangsan.fly();

封装:

封装有三个属性 (ES6不支持,可以TS演示)

Public 完全开放

Protected 对子类开放

Private 对自己开放

可以用于数据权限和保密

封装的特点

1.减少耦合,不该外露的不外露

2.利于数据的权限管理

3.ES6目前不支持,一般默认用_开头的属性是private

代码示例:

class People {
  // ES6通过constructor()方法 ,构造器来实现
  public name: string;
  public age: number;
  constructor(name: string, age: number) {
    // 实例属性
    this.name = name;
    this.age = age;
  }
  say(): void {
    //void 没有返回值
    console.log("我会说话!");
  }
}
// 子类继承父类
class Student extends People {
  public num: string;
  constructor(name: string, age: number, num: string) {
    super(name, age);
    this.num = num;
  }
  study(): void {
    console.log(`我的名字叫${this.name},年龄是${this.age}`);
  }
}

const stuA = new Student("李强", 5, "A1");
stuA.study();
console.log(stuA.name); 
// 因为此时name是public公开的,所以外部可以访问到,如果改成protected,就无法被外部访问了,只能被子类访问

// 封装:找到变化并且把它封装起来,你就可以在不影响其它部分的情况下修改或扩展被封装的变化部分,
// 这是所有设计模式的基础,就是封装变化,因此封装的作用,就解决了程序的可扩展性。

多态:

同一接口不同表现(js应用极少),需要结合其它强类型语言的重写、重载等功能。

ECMAScript中为什么没有函数重载概念?

因为在ES中函数都是对象,函数名实际上是一个指向函数的指针,并不与函数绑定,例如:

function add(a){ // 第一个add函数
    return a+1;
}
function add(a,b){ // 第二个add函数
    return a+b;
}
console.log(add(1)); // NaN
console.log(add(2,3)); // 5

上面代码中,如果是c++或者java等强类型语言,可以分别输出2和5;但是在js中,函数名仅仅只是保存了指向函数对象的指针,创建第二个函数add时,指针指向了新的函数对象,所以第一个函数并没有起任何作用。

总结

什么是面向对象?

面向对象程序设计(OOP)是种具有对象概念的程序编程典范。它是数据、属性、方法的集合。

面向对象的优点?

将对象作为程序的基本单元,将程序和数据封装其中,可以提高代码的重用性灵活性扩展性

面向对象三要素?

继承、封装、多态