前言
虽然JS是单线程的,但是我们学习可不能单线程。利用学习Nodejs的边边角角之余,我看了些关于JS设计模式的课程,感觉是值得总结与分享的,一来可以提高自己对JS编程的认知,二来可以在实际项目中设计出简单而优雅的设计方案。 因为这个课程看的比较慢,准备分三到四篇写完,分别为面向对象编程、五大设计原则、二十三种设计模式。
何为面向对象编程
最早接触这个词语也是在学C语言的时候,那时候老师说C是一个基于面向过程的编程语言,与之相对应的就是面向对象。所谓对象,通俗来说就是某一个事物所有属性和方法的集合。比如一个人的属性就有姓名、年龄、身高、体重等等,方法则是吃饭、睡觉、说话等。下面这个例子就是简单的写了个人的构造函数People,它的实例person1 就是一个 对象。它包括人的属性和方法,对象的本质其实就是一个结构化设计的方法,把相关的属性和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式。
class People {
constructor(name, age) {
this.name = name // 姓名
this.age = age // 年龄姓名
}
// 方法
say() {
console.log(`hello, my name is ${this.name}, I m ${this.age} years old`)
}
}
const person1 = new People('yellowbird', 25)
person1.say() // 打印hello, my name is yellowbird, I m 25 years old
面向对象编程的三要素
- 继承
继承性在JS中是相当重要的存在,所谓继承就是定义的子类也同时拥有父类的属性和方法,它最大的有点是可以抽离公共方法,减少代码冗余。还是举个例子,比如学生是人类组成的其中一个子类,他可以拥有人类所有的属性和方法,如姓名年龄,吃饭睡觉他都有,但他也有他独有的属性例如学校,学号等。写个例子简单感受一下继承。
class Student extends People {
constructor(name, age, grade) {
super(name, age)
this.grade = grade
}
study() {
console.log(`my name is ${this.name}, my grade is ${this.grade}`)
}
}
const student = new Student('yellowbird', 7, 'one')
student.study() //my name is yellowbird, my grade is one
student.say() // hello, my name is yellowbird, I m 7 years old
- 封装
所谓封装,就是隐藏方法和属性,只对外暴露公开接口。总所周知,JS是一门弱类型编程语言,所以其实封装这一概念并没有在JS中引入。而在Typescript中是有引入的。简单了解一下就ok了,为日后用到做好准备! 封装有3个关键字,分别为public(公有,不写为默认值),private(私有),protected(受保护的)。 我通过把上面继承的例子用TS改写的同时,来介绍一下它们的特点。
1、public
首先是public,它声明在变量之前,代表它可以在任何情况下被访问,不写通常默认为public。
class People {
public name: string;
public age: number;
public constructor(name , age) {
this.name = name; // 姓名
this.age = age; // 年龄姓名
}
// 方法
public say() {
console.log(`hello, my name is ${this.name}, I m ${this.age} years old`);
}
}
const person1 = new People('yellowbird', 25);
person1.say(); // 打印hello, my name is yellowbird, I m 25 years old,
2、private
它在被声明之后,无法在外部访问该变量,举个例子,人们并不想把自己的身份证号被人随意获取。所以就有如下代码
class People {
public name: string;
public age: number;
private id: string;
public constructor(name, age, id) {
this.name = name; // 姓名
this.age = age; // 年龄姓名
this.id = id;
}
// 方法
public say() {
console.log(`hello, my name is ${this.name}, I m ${this.age} years old`);
}
}
const person1 = new People('yellowbird', 25, '334111202008010129');
console.log('person1.id'); '// 私有变量无法被直接访问,报错
3、protected
它和private很相似,但是区别在于它的子类是可以访问被protected声明的属性。比如,我们不希望自己的体重被人直接获取到,但是作为学生去体检的时候会获取到体重值。
class People {
public name: string;
public age: number;
protected weight: number;
public constructor(name, age, weight) {
this.name = name; // 姓名
this.age = age; // 年龄姓名
this.weight = weight;
}
// 方法
public say() {
console.log(`hello, my name is ${this.name}, I m ${this.age} years old`);
}
}
class Student extends People {
constructor(name, age, weight) {
super(name, age, weight);
}
getWeight() {
console.log(`my weight is ${this.weight} kg`);
}
}
const student = new Student('yellowbird', 25, 100);
student.getWeight(); // 打印my weight is 100 kg
console.log(student.weight); // 报错
另外,构造函数constructor也可以被声明为protected,被声明之后,该构造函数无法实例化,但可以被继承。
class People {
public name: string;
public age: number;
protected weight: number;
protected constructor(name, age, weight) {
this.name = name; // 姓名
this.age = age; // 年龄姓名
this.weight = weight;
}
// 方法
public say() {
console.log(`hello, my name is ${this.name}, I m ${this.age} years old`);
}
}
class Student extends People {
constructor(name, age, weight) {
super(name, age, weight);
}
getWeight() {
console.log(`my weight is ${this.weight} kg`);
}
}
const student = new Student('yellowbird', 25, 100); // 可以继承
const person1 = new People('HP', 25, 200); // 报错, People不可以实例化
以上就是封装的解析和示例,大家细品,再结合手打代码,对封装一定会有进一步的理解。封装的作用主要是减少代码耦合,利于数据和接口的权限管理,如果你单纯用JS进行开发可能不太用得到,但是还是需要掌握的。
- 多态
所谓多态,就是用不同方式实现同一个接口。多态在JS使用就更少了,只能模拟一下,实际开发感觉真的不好用。思路其实就是用A和B分别去继承父类,然后重写不同的方法,如下:
class People {
constructor(name, age, weight) {
this.name = name; // 姓名
this.age = age; // 年龄姓名
}
// 方法
say() {
console.log(`hello, my name is ${this.name}, I m ${this.age} years old`);
}
}
class A extends People {
constructor(name, age) {
super(name, age,);
}
say() {
console.log('say A')
}
}
class B extends People {
constructor(name, age) {
super(name, age);
}
say() {
console.log('say B')
}
}
const a = new('a' ,20);
const b = new('b', 20);
a.say() // say A
b.say() // say B
总结一波
理解面向对象是这个JS设计模式系统讲解与应用的前置章节,可以说是为后面的二十三种设计模式铺路的。以前总说面向对象,但其实对这个概念并不是非常的理解,不去看,真的可能说不出它的三要素是什么,以及如何实现。获益良多,希望我的总结也能帮到大家~