JavaScript 设计模式----学习基础(面向对象)

1. 设计模式导读

1.1 如何成为一名合格工程师

  • 无论前端开发、客户端开发、后端开发都要学设计模式
  • 只懂代码不懂设计很难成为一名高级工程师

1.2 论工程师的设计能力

  • 前端开发有一定的设计能力
    • 3 年工作经验,面试必考设计能力
    • 成为项目技术负责人,设计能力是必要基础
    • 从写好代码,到做好设计,设计模式是必经之路

1.3 前端学习设计模式的困惑

  • 网上资料都是针对 Java 等后端语言的
  • 看懂概念,但是不知道怎么用,看完就忘
  • 现在的JS框架,到底都用了哪些设计模式

2. 面向对象

2.1 搭建开发环境

2.1.1 初始化 npm 环境
  • npm init
2.1.2 安装配置 webpack
  • 安装
    • npm install web pack webpack-cli --save-dev
    • 推荐淘宝镜像
    • npm install web pack webpack-cli --save-dev --registry=https://registry.npm.taobao.org
  • 配置 webpack.dev.config.js
module.exports = {
    
    
	entry: './src/index.js', // 唯一入口文件
	output: {
    
    
		path:__dirname, // 打包后文件存放的地方
		filename: './release/bundle.js' 
	}
}
  • 修改package.json
"scripts": {
    
    
	"test": "echo \"Error: no test specified\" && exit 1"
	"dev":"webpack --config ./webpack.dev.config.js --mode development" // 开发者模式
}
2.1.3 安装 webpack-dev-server
  • 安装插件
npm install webpack-dev-server html-webpack-plugin --save-dev
  • 修改 webpack.dev.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    
    
	entry: './src/index.js', // 唯一入口文件
	output: {
    
    
		path:__dirname, // 打包后文件存放的地方
		filename: './release/bundle.js' 
	},
	plugins: [ // 建立html模版,将打包生成的 bundle.js 自动插入到index.html模版中
		new HtmlWebpackPlugin({
    
    
			template: './index.html'
		})
	],
	devServer: {
    
     // 本地服务器
		contentBase: path.join(__dirname, './release'), // 根目录
		open: true, // 自动打开浏览器
		port: 9000 // 端口号
}
  • 修改package.json
"scripts": {
    
    
	"test": "echo \"Error: no test specified\" && exit 1"
	"dev":"webpack-dev-server --config ./webpack.dev.config.js --mode development" // 开发者模式
}
2.1.4 安装 babel
  • 安装插件
npm install babel-core babel-loader babel-polyfill babel-preset-es2015 babel-preset-latest --save-dev
  • 创建.babelrc文件
{
    
    
	"presets": ["es2015", "latest"],
    "plugins": []
}
  • 修改webpack.dev.config.js文件
module: {
    
     // 模块
   rules: [{
    
    
        test: /\.js?$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader' // 对检验的js文件进行babel处理(把ES6语法变成ES5语法)
    }]
}

2.2 什么是面向对象

2.2.1 面向对象概念
// 类,即模板
class People {
    
    
	constructor(name, age) {
    
    
		this.name = name
		this.age = age
	}
	eat() {
    
    
		alert(`${
      
      this.name} eat something`)
	}
	speak() {
    
    
		alert(`My name is ${
      
      this.name}, age ${
      
      this.age}`)
	}
}
  • 对象(实例)
// 创建实例
let zhang = new People('zhang', 20)
zhang.eat()
zhang.speak()

// 创建实例
let wang = new People('wang', 21)
wang.eat()
wang.speak()

2.3 面向对象–继承

2.3.1 继承的作用
  • 继承,子类继承父类
    • People 是父类,公共的,不仅仅服务于 Student
2.3.2 继承的特点
  • 继承可将公共方法抽离出来,提高复用,减少冗余
// 父类
class People {
    
    
    constructor(name, age) {
    
    
        this.name = name
        this.age = age
    }
    eat() {
    
    
        alert(`${
      
      this.name} eat something`)
    }
    speak() {
    
    
        alert(`My name is ${
      
      this.name}, age ${
      
      this.age}`)
    }
}

// 子类继承父类
class Student extends People {
    
     // extends 继承关键字
	constructor(name, age, number) {
    
    
		super(name, age) // 将name,age传递给父类来执行
		this.number = number
	}
	study() {
    
    
		alert(`${
      
      this.name} study`)
	}	
}

// 实例
let xiaoming = new Student('xiaoming', 10, 'A1')
xiaoming.study()
console.log(xiaoming.number)
xiaoming.eat()

let xiaohong = new Student('xiaohong', 11, 'A2')
xiaohong.study()
xiaohong.speak()

2.4 面向对象–封装

2.4.1 封装的作用
  • 封装,数据的权限和保密
    • public 完全开放
    • protected 对子类开放
    • private 对自己开放
2.4.2 封装的特点
  • 减少耦合,不该外露的不外露
    • 比如weight、girlfriend不想让外人访问,就不外露
    • 如果强行访问,会报错
    • 如果不这样,就要通过文档约束(仅限于人员少、沟通密切、没有恶意的情况下)
    • 一旦人多,比如上百个人员协作,文档不全,沟通不密切的情况下
    • 一旦访问又没有报错,万一出现线上问题就比较麻烦了
  • 利于数据、接口的权限管理
    • 一些安全性的隐私数据进行封装处理
  • ES6 目前不支持,一般认为_开头的属性是 private
// ES6 尚不支持,可以用 typescript 来演示
// 父类
class People {
    
    
	// typescript 定义属性
	name
	age
	protected weight // 定义 protected 属性,受保护的属性,只有自己或者子类可以访问
    constructor(name, age) {
    
    
        this.name = name
        this.age = age
        this.weight = 120
    }
    eat() {
    
    
        alert(`${
      
      this.name} eat something`)
    }
    speak() {
    
    
        alert(`My name is ${
      
      this.name}, age ${
      
      this.age}`)
    }
}

// 子类
class Student extends People {
    
    
	number
	private girlfriend // 定义 private 属性
	constructor(name, age, number) {
    
    
		super(name, age)
		this.number = number
		this.girlfriend = 'xiaoli'
	}
	study() {
    
    
		alert(`${
      
      this.name} study`)
	}
	getWeight() {
    
    
		alert(`weight ${
      
      this.weight}`)
	}
}

// 实例
let xiaoming = new Student('xiaoming', 10, 'A1')
xiaoming.getWeight()
// console.log(xiaoming.girlfriend) // 注意,编译时会报错,直接会编译不通过!
// girlfriend是私有属性,只能在子类内部访问

2.5 面向对象–多态

2.5.1 多态的作用
  • 同一接口不同实现
  • JS 应用极少
  • 需要结合 java 等语言的接口、重写、重载等功能
2.5.2 多态的特点
  • 保持子类的开放性和灵活性
    • 不是所有事情都让父类控制好,子类什么都不用做
    • 可以通过把公共的功能抽离出来,放在父类中去继承
    • 这样可以减少代码量,减少冗余,提高复用
    • 但是如果子类中需要进行灵活的处理,还是可以进行修改
  • 面向接口编程
    • 有时候不用管子类下面是如何实现的
    • 只需要管父类有多少接口,是怎么样的接口
    • JS 引用极少
class People {
    
    
	constructor(name) {
    
    
		this.name = name
	}
	saySomething() {
    
    
	
	}
}

class A extends People {
    
    
	constructor(name) {
    
    
		super(name)
	}
	saySomething() {
    
    
		alert('I am A')
	}
} 

class B extends People {
    
    
	constructor(name) {
    
    
		super(name)
	}
	saySomething() {
    
    
		alert('I am B')
	}
}

let a = new A('a')
a.saySomething()
let b = new B('b')
b.saySomething()

2.6 JS 应用举例

  • jQuery 是一个 class
  • $('p') 是 jQuery 的一个实例
class jQuery {
    
    
	constructor(selector) {
    
     // 构造函数
		let slice = Array.prototype.slice // 获取数组方法
		let dom = slice.call(document.querySelectorAll(selector)) // 获取dom节点
		let len = dom ? dom.length : 0 // dom数组的长度
		for (let i = 0; i < len; i++) {
    
    
			this.[i] = dom[i]
		}
		this.length = len
		this.selector = selector || ''
	}
	append(node) {
    
    
		// ...
	}
	addClass(name) {
    
    
		// ...
	}
	html(data) {
    
    
		// ...
	}
	// 此处省略若干 API
}

// 入口
window.$ = function (selector) {
    
    
	// 工厂模式
	return new jQuery(selector)
}

// 测试代码
var $p = $('p')
console.log($p)
console.log($p.addClass)

2.7 面向对象的意义

2.7.1 为何使用面向对象
  • 程序执行: 顺序、判断、循环 ———结构化
  • 面向对象 ——— 数据结构化
  • 对于计算机,结构化的才是最简单的
  • 编程应该 简单 & 抽象

3. UML 类图

  • Unified Modeling Language 统一建模语言
  • 类图,UML 包含很多种图,和设计模式相关的是类图
  • 关系,主要了解泛化关联

3.1 画图工具

3.2 类图

在这里插入图片描述

  • 实例
class People {
    
    
    constructor(name, age) {
    
    
        this.name = name
        this.age = age
    }
    eat() {
    
    
        alert(`${
      
      this.name} eat something`)
    }
    speak() {
    
    
        alert(`My name is ${
      
      this.name}, age ${
      
      this.age}`)
    }
}
  • 类图
    在这里插入图片描述

3.3 关系

  • 泛化,表示继承
  • 关联,表示引用

在这里插入图片描述

class People {
    
    
	constructor(name, house) {
    
     // 在People中引用house
		this.name = name
		this.house = house
	}
	saySomething() {
    
    
	
	}
}
class A extends People {
    
    
	constructor(name, house) {
    
    
		super(name, house)
	}
	saySomething() {
    
    
		alert('I am A')
	}
}

class B extends People {
    
    
	constructor(name, house) {
    
    
		super(name, house)
	}
	saySomething() {
    
    
		alert('I am B')
	}
}

class House {
    
    
	constructor(city) {
    
    
		this.city = city
	}
	showCity() {
    
    
		alert(`house in ${
      
      this.city}`)
	}
}

// 测试
let aHouse = new House('北京')
let a = new A('aaa', aHouse)
console.log(a) // a 有房子
let b = new B('bbb')
console.log(b) // b 无房子

猜你喜欢

转载自blog.csdn.net/qq_43645678/article/details/108962366