-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
设计模式初探 (2021-12-22) #28
Comments
单例模式定义:保证一个类只有一个实例,并提供一个访问它的全局访问点 /**
* 对现有的类,实现单例模式
* 代理类实现单例模式
*/
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()); |
策略模式
策略模式:定义一系列的算法,把她们一个个封装起来
模式目的:就是将算法的使用 和 算法的实现分离开来
The text was updated successfully, but these errors were encountered: