1. 工厂模式
作用:实现对象的批量创建
/* 构造函数 */
function Person(name) {
this.name = name;
}
function Car(model) {
this.model = model;
}
/* 创建 */
function create(type, val) {
return (this instanceof create) ?
this[type](val) : new create(type, val);
}
create.prototype = {
person: Person,
car: Car
}
console.log(create('person', 'zhangsan'))
console.log(new create('car', 'bwm'))
2. 原型模式
作用:创建一个共享原型,通过拷贝这个原型来创建新的类
// 也可以是其他类的原型
let prototype = {
say() {
console.log(this.name);
}
}
function Person() {
function F() { };
F.prototype = prototype;
let f = new F();
f.name = "zhansan";
return f;
}
new Person().say();// zhansan
3. 建造者模式
作用:将创建对象的细节分为创建子对象的过程,使结构更加清晰
/* 实现 */
function Person(name) {
this.name = name;
}
function CreateName(name) {
this.wholeName = name;
[this.firstName, this.lastName] = name.split(' ');
}
function CreateWork(workName) {
switch (workName) {
case 'engineer':
this.workName = "工程师";
this.desc = "热爱编程";
break;
case 'teacher':
this.workName = "老师";
this.desc = "热爱分享";
break;
default:
this.workName = workName;
this.desc = "无";
}
}
CreateWork.prototype.changeWork = function (workName, desc) {
workName && (this.workName = workName);
desc && (this.desc = desc);
}
/* 创建类 */
function Candidate(params) {
let _candidate = new Person();
_candidate.name = new CreateName(params.name);
_candidate.work = new CreateWork(params.work);
return _candidate;
}
/* 举例 */
let arr = [
{ name: "zhang san", work: "engineer" },
{ name: "li si", work: "teacher" }
];
let candidates = [];
arr.forEach(v => {
candidates.push(new Candidate(v));
})
console.log(candidates[0]);
candidates[0].work.changeWork('学生', '热爱学习');
console.log(candidates[0]);
4. 单例模式
作用:实现无论创建多少个对象都返回同一个
const createSingle = (function () {
let _unique = null;// 私有变量
return function () {
if (_unique === null) {
_unique = { a: 1 };
}
return _unique;
}
})();
let single1 = createSingle();
let single2 = createSingle();
console.log(single1 === single2);// true
5. 装饰器模式
作用:在不改变原有对象的基础上(也就是不修改原型),拓展功能和属性实现复杂逻辑
/**
* 4s店在卖一种车,价格为10万元,如果用户需要在此基础上加装一些配置则需要加钱。
* 比如加热座椅配置需要2万元,电动后视镜需要0.8万元等等。
*/
function Car(price) {
this.price = price;
}
// 通过函数实现改变(装饰器)
function addHeatSeat(car) {
car.hasHeatSeat = true;
car.price += 2;
}
function addAutoMirror(car) {
car.hasAutoMirror = true;
car.price += 0.8;
}
let car = new Car(10);
console.log(car);
// Car { price: 10 }
addHeatSeat(car);
addAutoMirror(car);
console.log(car);
// Car { price: 12.8, hasHeatSeat: true, hasAutoMirror: true }
6. 组合模式
作用:将每个组成成分当成一个对象,最终拼成一个整体
- 组合模式实现一个form表单
/* 继承原型 */
function inheritClass(Son, Parent) {
Son.prototype = Object.create(Parent.prototype);
Son.prototype.constructor = Son;
}
/* 父类 */
function Container() {
this.element = "";
}
Container.prototype = {
init() {
throw new Error("请重写子类init方法");
},
add(child) {
this.element.appendChild(child.element);
return this;
}
}
/* 表单 */
function Form(options) {
// 继承
Container.call(this);
// 参数
this.action = options.action || "/test.html";
this.method = options.method || "GET";
this.class = options.class || "";
this.id = options.id || "";
this.parentNode = options.parentNode;
this.init();
}
inheritClass(Form, Container);
Form.prototype.init = function () {
this.element = document.createElement('form');
this.element.setAttribute("action", this.action);
this.element.method = this.method;
this.element.class = this.class;
this.element.id = this.id;
}
Form.prototype.show = function () {
this.parentNode.appendChild(this.element);// 放入父元素
}
/* 标签 */
function Label(options) {
Container.call(this);
this.for = options.for || "";
this.class = options.class || "form-line";
this.innerText = options.innerText || "";
this.init();
}
inheritClass(Label, Container);
Label.prototype.init = function () {
this.element = document.createElement("label");
this.element.class = this.class;
this.element.setAtrribute("for",this.for);
this.element.innerText = this.innerText;
}
/* 输入 */
function Input(options) {
Container.call(this);
this.type = options.type || "text";
this.id = options.id || "";
this.value = options.value || "";
this.init();
}
inheritClass(Input, Container);
Input.prototype.init = function () {
this.element = document.createElement('input');
this.element.type = this.type;
this.element.id = this.id;
this.element.value = this.value;
}
/* -------------举例------------- */
let form = new Form({
action: '/aaa.html',
method: 'get',
id: "myForm",
parentNode: document.body
})
/* 三个div */
let user = new Div({ class: "form-line" })
.add(new Label({ for: 'user', innerText: "用户名" }))
.add(new Input({ type: "text", id: "user", name: "user" }));
let pwd = new Div({ class: "form-line" })
.add(new Label({ for: 'pwd', innerText: "密码" }))
.add(new Input({ type: "password", id: "pwd", name: "pwd" }));
let sub = new Div({ class: "form-line" })
.add(new Input({ type: "submit", id: "sub", value: "登录" }));
/* 加入 */
form.add(user).add(pwd).add(sub);
form.show();
7. 观察者模式
作用:一对多的关系,每当主体发生改变,订阅过它的个体将会收到通知
let msgCenter = (function () {
let events = {};
return {
/* 注册事件 */
register(type, fn) {
if (events[type]) {
events[type].push(fn);
} else {
events[type] = [fn];
}
},
/* 发布事件 */
fire(type, info) {
if (events[type]) {
events[type].forEach(fn => fn(info));
}
},
/* 取消事件 */
cancle(type, fn) {
if (events[type]) {
let index = events[type].indexOf(fn);
if (index !== -1)
events[type].splice(index, 1);
}
}
}
})();
function Person() {
this.alreadyRegister = {};
}
Person.prototype.register = function (type, fn) {
msgCenter.register(type, fn);
this.alreadyRegister[type] = fn;
}
Person.prototype.cancleEvent = function (type) {
let fn = this.alreadyRegister[type];
if (fn) {
msgCenter.cancle(type, fn);
delete fn;
}
}
// 举例
let person1 = new Person();
person1.register('news', (info) => {
console.log(`person1收到news,内容是 ${info}`)
});
let person2 = new Person();
person2.register('news', (info) => {
console.log(`person2收到news,内容是 ${info}`)
});
msgCenter.fire('news', 'testNews');
// person1收到news,内容是 testNews
// person2收到news,内容是 testNews
person1.cancleEvent('news');
msgCenter.fire('news', 'testNews2');
//person2收到news,内容是 testNews2
8. 策略模式
将所有的策略封装在一起,只给外部暴露出必要接口
<body>
<label for="phone">手机号</label>
<input type="text" id="input">
<script>
/* 策略 */
let strategy = (function () {
let _strategy = {
isEmpty(val) {
return val.length ? '' : '请输入手机号';
},
isPhone(val) {
return /^1[3-9][0-9]{9}/.test(val) ? '' : '请输入正确的手机号';
}
};
return {
validate(type, val) {
val = val.replace(/^\s+|\s+$/g, '');
return _strategy[type] ? _strategy[type](val) : '无该验证方法';
}
}
})();
// 验证输入框
input.onchange = function () {
let val = input.value;
let res = strategy.validate('isEmpty', val) || strategy.validate('isPhone', val) || '验证通过';
console.log(res);
}
</script>
</body>
9. 链模式
作用:通过返回自身的方式实现链式调用
let obj = {
a() {
console.log('aaa');
return this;
},
b() {
console.log('bbb');
return this;
}
};
// 调用
obj.a().b().a().b();
10. 代理模式
作用:多个对象处理同一事件时,可以将这个事件交给另一个对象统一处理
<body>
<ul id="ul">
<li>1</li>
<li>2</li>
</ul>
<script>
/* 点击每个li都会打印li内容 */
ul.onclick = function (e) {
if (e.target.nodeName.toLowerCase() === 'li') {
// 打印li内容
console.log(e.target.innerHTML);
}
}
// 新增的li也适用
let newLi = document.createElement('li');
newLi.innerHTML = '3';
ul.appendChild(newLi);
</script>
</body>
11. 访问者模式
作用:在不改变各元素的类的前提下定义作用于这些元素的新操作,将每一个类中的相关操作提取出来,包装成一个独立的对象,这个对象我们就称为访问者
let Visitor = (function () {
return {
splice() {
return Array.prototype.splice.call(...arguments);
},
push() {
return Array.prototype.push.call(...arguments);
}
}
})();
let obj = {};
Visitor.push(obj, 1)
Visitor.push(obj, 2);
console.log(obj);// { '0': 1, '1': 2, length: 2 }
Visitor.splice(obj, 0, 1);
console.log(obj);// { '0': 2, length: 1 }
12. 等待者模式
作用:通过多个异步进程监听,来触发未来发生的动作。
function Waiter() {
this.dfds = [];
this.doneArr = [];
this.failArr = [];
this.deferred = function () {
return new Promise(this);
}
}
Waiter.prototype = {
when(...fns) {
fns.forEach(fn => this.dfds.push(fn()));
return this;
},
done(...fns) {
this.doneArr = this.doneArr.concat(fns);
return this;
},
fail(...fns) {
this.failArr = this.failArr.concat(fns);
return this;
}
}
function Promise() {
this.resolved = false;
this.rejected = false;
this.waiter = waiter;
}
Promise.prototype = {
resolve() {
this.resolved = true;
/* 过滤已完成 */
this.waiter.dfds = this.waiter.dfds.filter(v => v.resolved === false);
/* 还有未完成则返回*/
if (this.waiter.dfds.length) return;
/* 全部执行完毕执行done回调 */
this.waiter.doneArr.forEach(fn => fn());
},
reject() {
this.rejected = true;
this.waiter.dfds.splice(0);// 删除所有Promise对象
this.waiter.failArr.forEach(fn => fn());// 执行所有失败回调
}
}
// 举例
let waiter = new Waiter();
function fn1() {
let dfd = waiter.deferred();
setTimeout(function () {
console.log("fn1 ok");
dfd.resolve();
}, 1000);
return dfd;// 返回Promise
}
function fn2() {
let dfd = waiter.deferred();
setTimeout(function () {
console.log("fn2 fail");
dfd.reject();
}, 1000 * 2);
return dfd;
}
waiter.when(fn1, fn2).done(function () {
console.log("done1");
}).done(function () {
console.log("done2");
}).fail(function () {
console.log('fail');
})