JavaScript 设计模式----单例模式

1. 单例模式

1.1 单例模式介绍

  • 系统中被唯一使用
  • 一个类只有一个实例

1.2 单例模式类图

  • 传统 UML 类图
    在这里插入图片描述

1.2 单例模式演示

  • 说明
    • 单例模式需要用到 java 的特性(private
    • ES6 中没有(TypeScript 除外)
    • 只能用 java 代码来演示 UML 图的内容
  • java 代码演示
public class SingleObject {
    
    
	// 注意,私有化构造函数,外部不能 new,只能内部能 new
	private SingleObject() {
    
    
		
	}
	// 唯一被 new 出来的对象
	private SingleObject instance = null;
	// 获取对象的唯一接口
	public SingleObject getInstance() {
    
    
		if (instance == null) {
    
    
			// 只 new 一次
			instance = new SingleObject();
		}
		return instance;
	}

	// 对象方法
	public void login(username, password) {
    
    
		System.out.println("login...");
	}
}
public class SingletonPatternDemo {
    
    
	public static void main(String[] args) {
    
    
		// 不合法的构造函数
		// 编译时错误:构造函数 SingleObject() 是不可见的
		// SingleObject object = new SingleObject();

		// 获取唯一可用的对象
		SingleObject object = SingleObject.getInstance();
		object.login();
	}
}
  • js 使用单例模式
class SingleObject {
    
     // 定义一个类
	login() {
    
     // 登陆方法(不是静态的)每初始化 Object 时,都会有 login 方法
		console.log('login...')
	}
	...
}
// 静态方法,getInstance 是挂载到 class 上的,无论 SingleObject 被 new 多少个,这个 getInstance 还是只有一个
SingleObject.getInstance = (function () {
    
     // 自执行函数
	// 通过闭包存储唯一个被初始化的实例
	let instance
	return function () {
    
    
		if (!instance) {
    
    
			instance = new SingleObject();
		}
		return instance
	}
})()
// 测试:注意这里只能使用静态函数 getInstance, 不能 new SingleObject()
let obj1 = SingleObject.getInstance()
obj1.login()
let obj2 = SingleObject.getInstance()
obj2.login()
console.log(obj1 === obj2) // 两者必须完全相等

let obj3 = new SingleObject() // 无法完全控制
obj3.login()
console.log(obj1 === obj3)

1.3 单例模式场景

1.3.1 jQuery 只有一个 $
  • jQuery 的全局函数是 $,只有一个
    • 如果一个页面中错误的将jQuery 代码引用好几遍,按理说应该有好几个或重复的 $,但是 jQuery 内部会处理
    • 如果检测到内部有 jQuery,就会直接返回,如果没有就会进行初始化操作
  • 多次初始化的问题
    • 消耗性能
    • 内部代码出现bug(比如多次渲染、多次统计等等)
// jQuery 只有一个 `$`
if (window.jquery != null) {
    
    
	return window.jQuery
} else {
    
    
	// 初始化...
}
1.3.2 模拟登录框
class LoginForm {
    
    
	constructor() {
    
    
		this.state = 'hide'
	}
	show() {
    
    
		if (this.state === 'show') {
    
    
			alert('已经显示')
			return
		}
		this.state = 'show'
		console.log('登录框已显示')
	}
	hide() {
    
    
		if (this.state === 'hide') {
    
    
			alert('已经隐藏')
			return
		}
		this.state = 'hide'
		console.log('登录框已隐藏')
	}
}
LoginForm.getInstance = (function() {
    
    
	let instance
	return function() {
    
    
		if(!instance) {
    
    
			instance = new LoginForm();
		}
		return instance
	}
})()
// 测试
let login1 = LoginForm.getInstance()
login1.show()

let login2 = LoginForm.getInstance()
login2.hide()

console.log(login1 === login2)
  • 购物车(和登录框类似)
1.3.3 vuex 和 redux 中的 store
  • 业务复杂度很高,每一块业务场景下获取 store,都必须是完全一样的,这样才能导致业务的数据同步
  • 模块A和模块B获取的 store 必须是完全一样的,可以共享
  • 如果模块A和模块B获取的 store 不一致,那模块A和模块B就不能通过 store 来进行数据共享数据传递,所以是单例模式

1.4 单例模式设计原则验证

  • 符合单一职责原则,只实例化唯一的对象
  • 没法具体开放封闭原则,但是绝对不违反开放封闭原则

猜你喜欢

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