单例模式
- 系统中被唯一使用的
- 一个类只有一个实例
实例
- 登录框
- 购物车
说明
- 单例模式需要用到 java 的特性(private)
- ES6 中没有 (typescript 除外)
- 只能用 Java 代码来演示 UML 图的内容
public class SingleObject {
// 注意, 私有化构造函数, 外部不能 new, 只能内部 new !!!
private SingleObject(){
}
// 唯一被 new 出来的对象
private SingleObject instance = null
// 获取对象的唯一接口
public SingleObject getInstance() [
if (instance == null) {
// 只能 new 一次
instance = new SingleObject()
}
]
// 对象方法
public void login(username, password) [
System.out.printIn('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() {
console.log("login...");
}
}
SingleObject.getInstance = (function() {
let instance;
return function() {
if (!instance) {
instance = new SingleObject();
}
return instance;
};
})();
// 测试: 注意这里只能使用静态函数 getInstance, 不能 new SingleObject() !!!
const obj1 = SingleObject.getInstance();
obj1.login();
const obj2 = SingleObject.getInstance();
obj2.login();
console.log(obj1 === obj2); // true
const obj3 = new SingleObject(); // 无法完全控制
obj3.login();
console.log(obj1 === obj3); // false
但是我们做不到 不能 new SingleObject(), 只能靠文档约束
场景
- jQuery
- 登录框
class LoginForm {
constructor() {
this.state = "hide";
}
show() {
if (this.state === "show") {
console.log("已经显示");
return;
}
this.state = "show";
console.log("登录框显示成功");
}
hide() {
if (this.state === "hide") {
console.log("已经隐藏");
return;
}
this.state = "hide";
console.log("登录框隐藏成功");
}
}
LoginForm.getInstance = (function() {
let instance;
return function() {
if (!instance) instance = new LoginForm();
return instance;
};
})();
// 测试
const login1 = LoginForm.getInstance();
login1.show();
const login2 = LoginForm.getInstance();
login2.hide();
console.log(login1 === login2); // true
- 其他
- 购物车 (和登录框类似)
- vuex 和 redux 中的 store
设计原则验证
- 符合单一职责原则, 只实例化唯一的对象
- 没法具体开放封闭原则, 但是绝对不违反开放封闭原则
网友评论