Open yaogengzhu opened 2 years ago
定义:保证一个类只有一个实例,并提供一个访问它的全局访问点 原理: 用一个变量那个来标志当前是否为莫个类创建过对象。
/**
* 对现有的类,实现单例模式
* 代理类实现单例模式
*/
class SingleMode {
constructor(name) {
this.name = name
}
getName() {
return this.name
}
}
const ProxySingleMode = (function(){
let instance
return function () {
if (!instance) {
instance = new SingleMode()
}
return instance
}
})()
// 类的实现
// class ProxySingleMode {
// static instance
// constructor() {
// if (!ProxySingleMode.instance) {
// ProxySingleMode.instance = new SingleMode()
// }
// return ProxySingleMode.instance;
// }
// }
const single = new ProxySingleMode()
const single1 = new ProxySingleMode()
console.log(single === single1) // true
惰性单列 定义: 指的是在需要的时候才创建的对象实例子
const getSingle = function (fn) {
let instance
return function () {
return instance || instance === fn.apply(this, arguments)
}
}
定义:代理是为一个对象提供一个替代品或者占位符,以便控制对它的访问
优点:对象本身不好处理的事情,交给代理处理
const Flower = function () {}
const xiaoming = {
sendFlower: function (target) {
const flower = new Flower()
target.receiveFlower(flower)
},
}
const A = {
receiveFlower: function (flower) {
console.log('收到花了')
},
}
const B = {
receiveFlower: function (flower) {
A.receiveFlower(flower)
},
}
xiaoming.sendFlower(B)
保护代理
和 虚拟代理
定义: 是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部状态
迭代器分为两种: 内部迭代
和外部迭代
内部迭代
const each = function (arr, callback) {
for (let i = 0; i < arr.length; i++) {
callback.call(arr[i], i, arr[i])
}
}
each([1, 2, 4], function (i, v) {
console.log(i, v)
})
外部迭代
外部迭代虽然调用方式相对复杂,但适用面更广,也能满足更多的需求。 内外迭代模式在生产中,没有优劣之分
const Iterator = function (obj) {
var current = 0
var next = function () {
current += 1
}
var isDone = function () {
return current >= obj.length
}
var getCurrentItem = function () {
return obj[current]
}
return {
next,
isDone,
getCurrentItem,
length: obj.length,
}
}
// 改写外部迭代模式
const compareOutter = function (iterator1, iterator2) {
if (iterator1.length !== iterator2.length) {
return console.log('iterator1 和 iterator2 不相等')
}
while (!iterator1.isDone() && !iterator2.isDone()) {
if (iterator1.getCurrentItem() !== iterator2.getCurrentItem()) {
return console.log('iterator1 和 iterator2 不相等')
}
iterator1.next()
iterator2.next()
}
console.log('相等')
}
let iterator1 = Iterator([1, 2, 3])
let iterator2 = Iterator([1, 2, 3, 4])
compareOutter(iterator1, iterator2)
倒叙迭代
const fallEach = function (arr, callback) {
for (let i = arr.length - 1; i >= 0; i--) {
callback(i, arr[i])
}
}
fallEach([1, 2, 3], function (i, k) {
console.log(i, k)
})
中止迭代
const breakEach = function (arr, callback) {
for (let i = 0; i < arr.length; i++) {
if (callback(i, arr[i]) === false) {
break
}
}
}
breakEach([1, 2, 3, 4], function (i, n) {
if (n > 3) return false
console.log(n)
})
迭代器的应用举例
根据浏览器环境获取不同的上传方式
const getActiveUploadObj = function() {
try {
retrun new ActiveXObject('IE上传')
} catch(e) {
return false
}
}
const getFlashUploadObj = function() {
if (supportFlash()) { // 省略该方法
var str = `<object type='xx'></object>` // 省写
return $(str).appendTo($('body'))
}
return false
}
const getFormUploadObj = function() {
var str = `<input type='file' />`
return $(str).appendTo($('body'))
}
const iteratorUploadObj = function() {
for (let i = 0; fn = arguments[i++]) {
const uploadObj = fn()
if (uploadObj !== false) {
return uploadObj
}
}
}
const uploadObj = iteratorUploadObj(getActiveUploadObj, getFlashUploadObj, getFormUploadObj)
用途: 用于执行一个特定事情的指令
const setCommad = function (button, command) {
button.click = function () {
command.execute()
}
}
const MenuBar = {
refresh: function () {
console.log('刷新')
},
}
const SubMenu = {
add: function () {
console.log('新增子菜单')
},
del: function () {
console.log('删除子菜单')
},
}
// 封装命令类
const RefreshMenuCommad = function (recevicer) {
this.recevicer = recevicer
}
RefreshMenuCommad.prototype.execute = function () {
this.recevicer.refresh()
}
const AddSubMenuCommand = function (recevicer) {
this.recevicer = recevicer
}
AddSubMenuCommand.prototype.execute = function () {
this.recevicer.add()
}
const DelSubMenuCommand = function (recevicer) {
this.recevicer = recevicer
}
DelSubMenuCommand.prototype.execute = function () {
// console.log('删除子菜单')
this.recevicer.del()
}
// 将命令接受者传入到command对象中,并且将command对象安装到button 上
const refreshMenuBarCommand = new RefreshMenuCommad(MenuBar)
const addSubMenuCommand = new AddSubMenuCommand(SubMenu)
const delSubMenuCommand = new DelSubMenuCommand(SubMenu)
setCommad(button1, refreshMenuBarCommand)
setCommad(button2, addSubMenuCommand)
setCommad(button3, delSubMenuCommand)
命令模式应用
// 游戏
const Ryu = {
attack: function () {
console.log('攻击')
},
defense: function () {
console.log('防御')
},
jump: function () {
console.log('跳跃')
},
crouch: function () {
console.log('蹲下')
},
}
// 创建命令
const makeCommand = function (recevicer, state) {
return function () {
recevicer[state]()
}
}
const commands = {
119: 'jump',
115: 'crouch',
97: ' defense',
100: 'attach',
}
const commandStack = [] // 保存命令栈
document.onKeypress = function (ev) {
const keyCode = ev.keyCode,
command = makeCommand(Ryu, commands[keyCode])
if (command) {
command()
commandStack.push(command) // 将刚执行过的命令推到栈里
}
}
// 点击播放录像
document.getElementById('replay').onclick = function () {
let command
while (command === commandStack.shift()) {
// 从堆栈里一次取出命令并执行
command()
}
}
宏命令
宏命令是一组命令的集合,通过执行宏命令,可以支持一次执行一批命令
// 依次创建好各种command
const closeDoorCommand = {
execute: function () {
console.log('关门')
},
}
const openPcCommand = {
execute: function () {
console.log('开电脑')
},
}
const openQQCommand = {
execute: function () {
console.log('登QQ')
},
}
const MaroCommand = function () {
return {
commandList: [],
add: function (command) {
this.commandList.push(command)
},
execute: function () {
this.commandList.forEach((fn) => fn.execute())
},
}
}
const macroCommand = new MaroCommand()
macroCommand.add(closeDoorCommand)
macroCommand.add(openPcCommand)
macroCommand.add(openQQCommand)
macroCommand.execute()
定义:使用多个对象处理请求,从而避免请求发送者和接收者之间的耦合关联,将这些对象连成一条链子,并沿着链子传递请求,直到有一个对象处理它为止
/**
* 普通函数写法
* @param {*} orderType 订单类型
* @param {*} pay 是否已支付
* @param {*} stock 库存数量
*/
const order = function (orderType, pay, stock) {
if (orderType === 1) {
if (pay === true) {
console.log('已付款500元定金,可以得到100优惠券')
} else {
if (stock > 0) {
console.log('普通购买,无优惠券')
} else {
console.log('库存不足')
}
}
} else if (orderType === 2) {
if (pay === true) {
console.log('已付款200元定金,可以得到50优惠券')
} else {
if (stock > 0) {
console.log('普通购买,无优惠券')
} else {
console.log('库存不足')
}
}
} else if (orderType === 3) {
if (stock > 0) {
console.log('普通购买,无优惠券')
} else {
console.log('库存不足')
}
}
}
// order(1, true, 500)
/**
* 职责链重构
*/
const order500 = function (orderType, pay, stock) {
if (orderType === 1 && pay === true) {
console.log('已付款500元定金,可以得到100优惠券')
} else {
order200(orderType, pay, stock)
}
}
const order200 = function (orderType, pay, stock) {
if (orderType === 2 && pay === true) {
console.log('已付款200元定金,可以得到50优惠券')
} else {
orderNormal(orderType, pay, stock)
}
}
const orderNormal = function (orderType, pay, stock) {
if (stock > 0) {
console.log('普通购买,无优惠券')
} else {
console.log('库存不足')
}
}
// order500(3, true, 500)
/**
* 升级写法
*/
const Chain = function (fn) {
this.fn = fn
this.successor = null // 表示职责链的下一个节点
}
/**
* 指定在链中的下一个节点
* @param {*} successor
* @returns
*/
Chain.prototype.setNextSuccessor = function (successor) {
return (this.successor = successor)
}
/**
* 传递请求给某一个节点
* @returns
*/
Chain.prototype.passRequest = function () {
let ret = this.fn.apply(this, arguments)
if (ret === 'nextSuccessor') {
return (
this.successor &&
this.successor.passRequest.apply(this.successor, arguments)
)
}
return ret
}
const upgradeOrder500 = function (orderType, pay, stock) {
if (orderType === 1 && pay === true) {
console.log('已付款500元定金,可以得到100优惠券')
} else {
return 'nextSuccessor'
}
}
const upgradeOrder200 = function (orderType, pay, stock) {
if (orderType === 2 && pay === true) {
console.log('已付款200元定金,可以得到50优惠券')
} else {
return 'nextSuccessor'
}
}
const upgradeOrderNormal = function (orderType, pay, stock) {
if (stock > 0) {
console.log('普通购买,无优惠券')
} else {
console.log('库存不足')
}
}
// 将3个订单的函数分别包装成职责链的节点
const chainOrder500 = new Chain(upgradeOrder500)
const chainOrder200 = new Chain(upgradeOrder200)
const chainNormal = new Chain(upgradeOrderNormal)
// 指定节点在职责链的顺序
chainOrder500.setNextSuccessor(chainOrder200)
chainOrder200.setNextSuccessor(chainNormal)
// 将请求传递给第一个节点
chainOrder500.passRequest(2, true, 500)
链表结合职责链模式
实现用来解决两个软件实体间接口不兼容的问题。
const google = {
show: function () {
console.log('渲染goggle地图')
},
}
const baidu = {
show: function () {
console.log('渲染baidu地图')
},
}
const renderMap = function (map) {
if (map.show instanceof Function) {
map.show()
}
}
renderMap(google)
renderMap(baidu)
/**
* 异常,不是show
*/
const newBaidu = {
display: function () {
console.log('渲染新百度地图')
},
}
const newBaiduAdapter = {
// 重新一个写一个方法来适配现有的结构
show: function () {
return newBaidu.display()
},
}
renderMap(newBaiduAdapter)
同一操作作用不同的对象上, 可以产生不同的解释和不同的执行结果
function renderMap(map) {
if (map.show instanceof Function) {
map.show()
}
}
class GoogleMap {
show() {
console.log('渲染Google地图')
}
}
class SogoMap {
show() {
console.log('渲染Sogo地图')
}
}
console.log(renderMap(new GoogleMap()))
console.log(renderMap(new SogoMap()))
实现一个计算cost(10)、cost(20)、cost(30)、最后通过cost() 得到最终的结果
思路:参数为空时,返回最终结果 可将参数存起来,判断参数为空时 在统计返回结果,需要利用到闭包的知识点;
const cost = (function () {
const args = []; // 存放参数
return function () {
// 判断参数是否为空, 参数为空,则表示需要直接返回最终结果
if (arguments.length === 0) {
let momeny = 0;
for (let i = 0; args.length === 0; i++) {
momeny += args[i];
}
return momeny;
} else {
// 如果参数存在,则将参数全部存到args 中
[].push.apply(args, arguments);
}
};
})();
通用方案
const cost = (function () {
let momeny = 0;
return function () {
for (let i = 0; i < arguments.length; i++) {
momeny += arguments[i];
}
return momeny;
};
})();
function currying(fn) {
const args = [];
return function () {
if (arguments.length == 0) {
return fn.apply(this, args);
} else {
[].push.apply(args, arguments);
return arguments.callee;
}
};
}
const fn = currying(cost);
fn(1)(2);
console.log(fn());
策略模式
策略模式:定义一系列的算法,把她们一个个封装起来 模式目的:就是将算法的使用 和 算法的实现分离开来