设计模式
回顾
ajax
ajax 是一个异步请求工具,主要提供对应的客户端和服务端之间的数据交互。它可以完成对应的局部刷新(同步加载页面整体会刷新,异步加载对应的页面不会进行刷新)核心对象 (XMLHttpRequest)
ajax的流程
-
创建xhr
-
打开链接
-
设置请求头(post请求)
-
发送请求
-
监听事件接收数据
get请求
get请求 数据携带在对应的url中
post请求
post需要设置对应的请求头 携带在请求体中
JSONP
解决对应的跨域的方案(主要利用script标签不受跨域的影响 通过回调函数来接收对应的数据)
步骤
准备一个回调函数
使用script标签链入对应的地址 传入参数及回调函数
加载完成 删除对应的script标签
设计模式
概述
设计模式是对应的一些处理方案形成的思想来构成的模式。主要针对的是类和对象的设计和构造。他不区分语言,共23总设计模式(主要用于 架构设计 和 源码设计)
设计模式的分类
-
创建型模式 (关于对应的创建)
-
结构型模式 (将多个小结构并入一个大结构)
-
行为型模式 (关于对象的行为处理)
设计模式分类图
设计模式的七大原则
-
单一责任原则 一个类只负责一个功能领域中的相应职责,或者说一个类应该只有一个变化的原因
-
开闭原则 一个软件实体, 如类, 模块, 函数等应该对扩展开放, 对修改封闭.
-
里氏置换原则 子类型(subtype)必须能够替换掉他们的基类型(base type)
-
依赖倒转原则 高层模块不应该依赖低层模块,二者都应该依赖其抽象 抽象(接口/抽象类)不应该依赖细节(类),细节应该依赖抽象
-
接口隔离原则 接口尽量细化,接口中的方法尽量少
-
迪米特法则 如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中的一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
-
合成复用原则 它要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
创建型模式(工厂模式、单例模式)
工厂模式
以工厂的形式来生产对象(不关注对象的细节)
function factoly(){
// 创建对象
let obj={}
// 属性赋值
obj.name=name
// 返回对象
return obj
}
单例模式(懒汉、饿汉)
保证产生的对象只有一个(不会被污染)
// 利用闭包实现
function singleton(){
let only = null
retutn function(){
// 判断对象是否是null
// 如果为null产生新的对象
if(!only){
only=new Object()
}
return only
}
}
let onlyFN = singleton()
let obj = onlyFN()
let obj2=onlyFN()
console.log(obj == obj2)// true
// 利用原型来实现
function singletonProto(){
// 判断是否存在该对象
if(!Object.prototype.single){
Object.prototype.single = new Object()
}
return Object.prototype.single
}
let onlyFN = singletonProto()
let obj = singletonProto()
console.log(obj == onlyFN)// true
// 利用静态属性实现
function singletonStatic(){
if(!Object.single){
Object.single = new Object()
}
return Object.single
}
let onlyFN = singletonStatic()
let obj = singletonStatic()
console.log(obj == onlyFN)// true
// 使用global对象实现
function singletonGlobal(){
if(!globalThis.single){ // globalThis 这里指向是window
globalThis.single = new Object()
}
return globalThis.single
}
let onlyFN = singletonGlobal()
let obj = singletonGlobal()
console.log(obj == onlyFN)// true
结构型模式(代理模式、装饰器模式、组合模式)
组合模式
将多个小结构组合成一个大结构
function playgame(){
this.init=()=>{
console.log('开机')
}
}
function Gohome(){
this.init=()=>{
console.log('回家')
}
}
function Run(){
this.init=()=>{
console.log('洗脚')
}
}
// 洗脚回家打游戏
new Run().init()
new Gohome().init()
new playgame().init()
将init 方法一起执行 利用组合模式来执行多个同名方法
function combination(){
this.objs=[]
// 传入对应的对象数组
this.add= function(
组合模式的应用 vue 里面use 和 install
class Vue {
// 解析对应的对象 执行对应的install
static use(
装饰器模式
用一个新的类将对应的原本的对象进行包装在进行加强(在不改变原对象的基础上进行增强)
function person(){
this.run = function(){
console.log('跑')
}
}
// 先传入要增强的对象 返回一个新对象
function stronger(){
this.person = person
this.fly = function(){
this.person.run()
console.log('我会飞')
}
}
let person=person()
ts内置有对应的装饰器 Decorator TS 中使用注解来进行对应的装饰器添加@decorator
代理模式
代理模式是在原有对象的基础上增强对应的对象(利用代理对象来增强)代理对象通常访问的是实际对象
示例
我(原本对象)请了秘书(代理),秘书给我管钱(功能增强),当秘书(代理)把钱花完了(我(原本对象)的前也没有了)
-
代理对象对原本的对象进行了功能增强
-
代理对象影响的是实际的对象
ES7新增了Proxy的类 来帮助我们进行代理
Proxy(VUE3的底层实现)
实例化(传入对应的被代理对象 处理对象 产生一个代理对象)
var proxy = new Proxy(target,handler)
示例
// 被代理对象
var object = {name:'张三',age:18}
// 代理对象 传入被代理对象 处理对象
var proxy=new Proxy(object,{
// 获取属性名 代理对象 被代理对象
get(targetObj, attributeName, proxyObj){
},
//设置相关的属性 属性名 代理对象 被代理对象 处理对象
set(targetObj, attributeName, attributeValue, proxyObj){
},
// 目标对象 对应的属性 默认返回false 使用in关键词
has(target,p){
return p in target
},
deleteProperty(targetObj, attribute){
delete targetObj[attribute]
}
})
行为型模式(观察者模式)了解(访问者模式、解释器模式)
观察者模式
观察者模式是前端最常用的模式,它相当于对应的监听和处理执行的机制。观察者模式别名observer 又被称为发布者订阅者模式
常见的发布订阅者模式
addEventListener(事件监听器)
// box.addEventListener(事件名,handler)
box.addEventListener('click',function(){
console.log('点击了')
})
-
你 发布者(box添加点击事件)
-
js事件处理引擎 订阅者(添加事件监听 保持监听)
-
处理 处理函数 订阅者(订阅者进行处理)
实现一个发布者订阅者模式
模仿EventListener来实现
-
事件监听
-
事件执行
-
事件取消
class Observer {
constructor() {
// 存储事件的容器和处理函数的容器
this.events = {}
}
// 监听事件传入一个事件名和对应的处理函数
on(eventName, handler) {
// 判断是否存储了对应的事件 如果存储了就加到数组内
if (eventName in this.events) {
this.events[eventName].add(handler)
} else {
// 使用set保证没有重复
this.events[eventName] = new Set([handler])
}
}
// 执行对应的处理函数 传入对应的事件 执行对应的处理函数 传入对应的参数传给处理函数
emit(eventName,...args) {
// 不存在 跳出
if(!this.events[eventName]) return;
// 存在 遍历对应的集合 调用的对应的处理函数
this.events[eventName].forEach((handler)=>{
handler.apply(this,args)
})
}
// 移除事件监听
off(eventName,handler) {
// 查询是否具备对应的事件
// 不具备 跳出
if(!this.events[eventName]) return;
// 具备 删除
// 遍历对应的处理函数数组
this.events[eventName].delete(handler)
}
}
总结
-
off是用于取消事件
-
on 是用于监听事件
-
emit是用于执行事件
-
存储使用的对象进行存储
-
emit传入的参数可以被处理函数接收
-
浙公网安备 33010602011771号