時間:2024-02-08 02:30:01 | 來源:網(wǎng)站運營
時間:2024-02-08 02:30:01 來源:網(wǎng)站運營
web前端的設(shè)計模式是什么?:什么是設(shè)計模式?我們?yōu)槭裁葱枰獙W習設(shè)計模式?function getPrice(originalPrice, status){ // ... return price }
其實,面對這樣的問題,如果不考慮任何設(shè)計模式,最直觀的寫法可能就是使用if-else通過多個判斷語句來計算價格。function getPrice(originalPrice, status) { if (status === 'pre-sale') { return originalPrice * 0.8 } if (status === 'promotion') { if (origialPrice <= 100) { return origialPrice * 0.9 } else { return originalPrice - 20 } } if (status === 'default') { return originalPrice }}
有三個條件;然后,我們寫三個 if 語句,這是非常直觀的代碼。function getPrice(originalPrice, status) { if (status === 'pre-sale') { return originalPrice * 0.8 } if (status === 'promotion') { if (origialPrice <= 100) { return origialPrice * 0.9 } else { return originalPrice - 20 } } if (status === 'black-friday') { if (origialPrice >= 100 && originalPrice < 200) { return origialPrice - 20 } else if (originalPrice >= 200) { return originalPrice - 50 } else { return originalPrice * 0.8 } } if(status === 'default'){ return originalPrice }}
每當我們增加或減少折扣時,我們都需要更改函數(shù)。這種做法違反了開閉原則。修改已有函數(shù)很容易出現(xiàn)新的錯誤,也會讓getPrice越來越臃腫。function preSalePrice(origialPrice) { return originalPrice * 0.8}function promotionPrice(origialPrice) { if (origialPrice <= 100) { return origialPrice * 0.9 } else { return originalPrice - 20 }}function blackFridayPrice(origialPrice) { if (origialPrice >= 100 && originalPrice < 200) { return origialPrice - 20 } else if (originalPrice >= 200) { return originalPrice - 50 } else { return originalPrice * 0.8 }}function defaultPrice(origialPrice) { return origialPrice}function getPrice(originalPrice, status) { if (status === 'pre-sale') { return preSalePrice(originalPrice) } if (status === 'promotion') { return promotionPrice(originalPrice) } if (status === 'black-friday') { return blackFridayPrice(originalPrice) } if(status === 'default'){ return defaultPrice(originalPrice) }}
經(jīng)過這次修改,雖然代碼行數(shù)增加了,但是可讀性有了明顯的提升。我們的main函數(shù)顯然沒有那么臃腫,寫單元測試也比較方便。let priceStrategies = { 'pre-sale': preSalePrice, 'promotion': promotionPrice, 'black-friday': blackFridayPrice, 'default': defaultPrice}
我們將狀態(tài)與折扣策略結(jié)合起來。那么計算價格會很簡單:function getPrice(originalPrice, status) { return priceStrategies[status](originalPrice)}
這時候如果需要增減折扣策略,不需要修改getPrice函數(shù),我們只需在priceStrategies對象中增減一個映射關(guān)系即可。function weatherWarning(){ buildingsite.stopwork() ships.mooring() tourists.canceltrip()}
這是一種非常直觀的寫法,但是這種寫法有很多不好的地方:const EventEmit = function() { this.events = {}; this.on = function(name, cb) { if (this.events[name]) { this.events[name].push(cb); } else { this.events[name] = [cb]; } }; this.trigger = function(name, ...arg) { if (this.events[name]) { this.events[name].forEach(eventListener => { eventListener(...arg); }); } };};
我們之前的代碼,重構(gòu)以后變成這樣:let weatherEvent = new EventEmit()weatherEvent.on('warning', function () { // buildingsite.stopwork() console.log('buildingsite.stopwork()')})weatherEvent.on('warning', function () { // ships.mooring() console.log('ships.mooring()')})weatherEvent.on('warning', function () { // tourists.canceltrip() console.log('tourists.canceltrip()')})weatherEvent.trigger('warning')
如果你的項目中存在多對一的依賴,并且每個模塊相對獨立,那么你可以考慮使用發(fā)布-訂閱模式來重構(gòu)你的代碼。element.addEventListener('click', function(){ //...})// this is also publish-subscribe pattern
<ul id="container"> <li>Jon</li> <li>Jack</li> <li>bytefish</li> <li>Rock Lee</li> <li>Bob</li> </ul>
我們想給頁面添加一個效果:每當用戶點擊列表中的每個項目時,都會彈出一條消息:Hi, I'm ${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>Proxy Pattern</title></head><body> <ul id="container"> <li>Jon</li> <li>Jack</li> <li>bytefish</li> <li>Rock Lee</li> <li>Bob</li> </ul> <script> let container = document.getElementById('container') Array.prototype.forEach.call(container.children, node => { node.addEventListener('click', function(e){ e.preventDefault() alert(`Hi, I'm ${e.target.innerText}`) }) })</script></body></html>
這種方法可以滿足要求,但這樣做的缺點是性能開銷,因為每個 li 標簽都綁定到一個事件。如果列表中有數(shù)千個元素,我們是否綁定了數(shù)千個事件? let container = document.getElementById('container') container.addEventListener('click', function (e) { console.log(e) if (e.target.nodeName === 'LI') { e.preventDefault() alert(`Hi, I'm ${e.target.innerText}`) } })
這實際上是代理模式。function compute(str) { // Suppose the calculation in the funtion is very time consuming console.log('2000s have passed') return 'a result'}
現(xiàn)在需要給這個函數(shù)添加一個緩存函數(shù):每次計算后,存儲參數(shù)和對應(yīng)的結(jié)果。在接下來的計算中,會先從緩存中查詢計算結(jié)果。const proxyCompute = (function (fn){ // Create an object to store the results returned after each function execution. const cache = Object.create(null); // Returns the wrapped function return function (str) { // If the cache is not hit, the function will be executed if ( !cache[str] ) { let result = fn(str); // Store the result of the function execution in the cache cache[str] = result; } return cache[str] }})(compute)
這樣,我們可以在不修改原函數(shù)技術(shù)的 情況下為其擴展計算函數(shù)。關(guān)鍵詞:模式,設(shè)計,端的
微信公眾號
版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。