享元模式的核心是 对象池,使用对象时,先从对象池中获取对象,如果对象池中没有,创建一个,放入对象池,然后再从对象池中获取(只能从对象池中拿对象,不能自己创建);
- 共享内存,节约内存空间;
- 相同的数据 共享使用;
- 主要还是对 数据、方法共享分离,将数据的方法分为 内部数据、内部方法 和 外部数据、外部方法;
- 内部状态 保存在对象内部,通常不会改变,可以共享;
- 外部状态 保存在对象外部,可以随场景改变,不可以共享;
适用场景:
- 底层开发:某个系统的底层开发,对性能要求比较高,可使用享元模式;
- 缓冲池:系统中实例对象数量庞大,需要缓冲池处理这些对象;
优点:
- 降低内存占用:减少在内存中创建对象的数量,节省了内存,提高了效率;
- 减少创建对象开销:创建对象时需要占用一定的开销,如 new 操作; 可能构造函数中有访问 文件、数据库、网络 等操作,也可以避免这些开销;
缺点:
- 增加复杂性:将一个类拆解成多个类,系统复杂性肯定增加了;
类图
代码
function Person(name, age) {
// 私有
this.name = name;
this.age = age;
}
// 公有
Person.prototype.getAge = function () {
console.log(this.age)
}
// 公有
Person.prototype.getName = function () {
console.log(this.name)
}
场景
对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<input type="radio" value="red" name="color" checked />红
<input type="radio" value="yellow" name="color" />黄
<input type="radio" value="blue" name="color" />蓝
<button onclick="draw()">绘制</button>
<div id="container"></div>
</body>
<script>
let container = document.getElementById('container');
class MyDiv {
constructor() {
// 共享 div 容器 container,不需要每次重新创建
this.element = document.createElement('div');
}
setColor(color) {
this.element.style = `width:100px; height:100px; background-color:${color};`;
}
}
let div = new MyDiv();
function draw() {
let color = Array.from(document.getElementsByName('color')).find(item => item.checked).value || 'red';
div.setColor(color);
container.appendChild(div.element);
}
</script>
</html>
分页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<ul id="news"></ul>
<button id="nextPage" onclick="goNext()">下一页</button>
</body>
<script>
let list = [];
for (let i = 0; i < 20; i++) {
list[i] = `新闻${i + 1}`
}
let getLi = (function () {
let lis = [];
return function () {
let element;
if (lis.length < 5) {
element = document.createElement('li');
lis.push(element);
} else {
// 共享 dom,不需要每次重新创建
element = lis.shift();
lis.push(element);
}
return element;
}
})();
let pageNum = 0;
let pageSize = 5;
let news = document.getElementById('news');
function goNext() {
pageNum++;
let start = (pageNum - 1) * pageSize;
for (let i = 1; i <= 5; i++) {
let element = getLi();
element.innerHTML = `新闻${start + i}`;
news.appendChild(element);
}
}
goNext();
</script>
</html>
命令模式
上一篇