前端开发者对于JQ肯定是非常熟悉的,接下来便通过JQ的简单实现讲解工厂模式
首先准备html和css
HTML: 简单的一个无序列表
<ul>
<li>11</li>
<li>22</li>
<li>33</li>
</ul>
复制代码
CSS:仅仅写了一个样式类,便于接下来操作使用
.red {
color: red;
}
复制代码
现在有个需求,需要将li的内容变为红色
简单粗暴的实现方式:
const elements = document.querySelectorAll('li')
for (let i = 0; i < elements.length; i++) {
elements[i].classList.add('red')
}
复制代码
此时已经满足要求,那么接下来需求变更,需要将页面中P的标签内容都变为绿色,上述实现代码仅需要修改两处便可以实现
-- const elements = document.querySelectorAll('li')
++ const elements = document.querySelectorAll('p')
for (let i = 0; i < elements.length; i++) {
-- elements[i].classList.add('red')
++ elements[i].classList.add('green')
}
复制代码
此时最简单的优化便是将代码抽离为函数
const addClassByEle = (selectr, className) => {
const elements = document.querySelectorAll(selectr)
for (let i = 0; i < elements.length; i++) {
elements[i].classList.add(className)
}
}
addClassByEle('li', 'red');
复制代码
此时已经满足功能需求和函数的抽离,但是一个函数做了太多的事情,距离我们的目标还有一些距离
接下来看一看,通过工厂模式进行封装:
class JQuery {
constructor(selector) {
this.selector = selector;
const elements = document.querySelectorAll(selector);
this.length = elements.length;
for (let i = 0; i < elements.length; i++) {
this[i] = elements[i];
}
}
addClass(className) {
for (let i = 0; i < this.length; i++) {
this[i].classList.add(className);
}
}
}
/**
* 工厂函数
*/
window.$ = function (selector) {
return new JQuery(selector);
};
window.onload = () => {
const elements = $("li");
elements.addClass("red");
};
复制代码
通过代码可以看到,$函数即为一个工厂模式,我们调用其便可以创建我们需要的实例化对象,不需要关心具体的实现,addClass负责职责单一原则,整个JQuery对扩展是完全开放的,同时也并没有提供修改内部的方法,符合开放封闭原则