自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

這需求快讓我崩潰了,不過(guò)幸虧我懂裝飾器模式

開(kāi)發(fā) 前端
裝飾器模式是一種非常有用的設(shè)計(jì)模式,在項(xiàng)目中也會(huì)經(jīng)常用到,當(dāng)需求變動(dòng)時(shí),覺(jué)得某個(gè)邏輯很多余,那么直接不裝飾它就行了,也不需要去修改實(shí)現(xiàn)邏輯的代碼。

[[398737]]

目的

裝飾器模式(Decorator Pattern) 的目的非常簡(jiǎn)單,那就是:

在不修改原有代碼的情況下增加邏輯。

這句話聽(tīng)起來(lái)可能有些矛盾,既然都要增加邏輯了,怎么可能不去修改原有的代碼?但 SOLID (向?qū)ο笤O(shè)計(jì)5大重要原則)的開(kāi)放封閉原則就是在試圖解決這個(gè)問(wèn)題,其內(nèi)容是不去改動(dòng)已經(jīng)寫(xiě)好的核心邏輯,但又能夠擴(kuò)充新邏輯,也就是對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。

舉個(gè)例子,假如產(chǎn)品的需求是實(shí)現(xiàn)一個(gè)專(zhuān)門(mén)在瀏覽器的控制臺(tái)中輸出文本的功能,你可能會(huì)這樣做:

  1. class Printer { 
  2.   print(text) { 
  3.     console.log(text); 
  4.   } 
  5.  
  6. const printer = new Printer(); 
  7. printer.print('something'); // something 

在你滿意的看著自己的成果時(shí),產(chǎn)品過(guò)來(lái)說(shuō)了一句:“我覺(jué)得顏色不夠突出,還是把它改成黃色的吧!”

[[398738]]

小菜一碟!你自信的打開(kāi)百度一通操作之后,把代碼改成了下面這樣子:

  1. class Printer { 
  2.   print(text) { 
  3.     console.log(`%c${text}`,'color: yellow;'); 
  4.   } 

但產(chǎn)品看了看又說(shuō):“這個(gè)字體有點(diǎn)太小了,再大一點(diǎn),最好是高端大氣上檔次那種。

”好吧。。。“你強(qiáng)行控制著自己拿刀的沖動(dòng),一邊琢磨多大的字體才是高端大氣上檔次,一邊修改 print 的代碼:

  1. class Printer { 
  2.   print(text) { 
  3.     console.log(`%c${text}`,'color: yellow;font-size: 36px;'); 
  4.   } 

這次改完你之后你心中已經(jīng)滿是 mmp 了,而且偷偷給產(chǎn)品貼了個(gè)標(biāo)簽:

[[398739]]

你無(wú)法保證這次是最后的修改,而且也可能會(huì)不只一個(gè)產(chǎn)品來(lái)對(duì)你指手劃腳。你呆呆的看著顯示器,直到電腦進(jìn)入休眠模式,屏幕中映出你那張苦大仇深的臉,想著不斷變得亂七八糟的 print 方法,不知道該怎么去應(yīng)付那些永無(wú)休止的需求。。。

[[398740]]

在上面的例子中,最開(kāi)始的 Printer 按照需求寫(xiě)出它應(yīng)該要有的邏輯,那就是在控制臺(tái)中輸出一些文本。換句話說(shuō),當(dāng)寫(xiě)完“在控制臺(tái)中輸出一些文本”這段邏輯后,就能將 Printer 結(jié)束了,因?yàn)樗褪? Printer 的全部邏輯了。那在這個(gè)情況下該如何改變字體或是顏色的邏輯呢?

這時(shí)你該需要裝飾器模式了。

Decorator Pattern(裝飾器模式)

首先修改原來(lái)的 Printer,使它可以支持?jǐn)U充樣式:

  1. class Printer { 
  2.   print(text = ''style = '') { 
  3.     console.log(`%c${text}`, style); 
  4.   } 

之后分別創(chuàng)建改變字體和顏色的裝飾器:

  1. const yellowStyle = (printer) => ({ 
  2.   ...printer, 
  3.   print: (text = ''style = '') => { 
  4.     printer.print(text, `${style}color: yellow;`); 
  5.   } 
  6. }); 
  7.  
  8. const boldStyle = (printer) => ({ 
  9.   ...printer, 
  10.   print: (text = ''style = '') => { 
  11.     printer.print(text, `${style}font-weight: bold;`); 
  12.   } 
  13. }); 
  14.  
  15. const bigSizeStyle = (printer) => ({ 
  16.   ...printer, 
  17.   print: (text = ''style = '') => { 
  18.     printer.print(text, `${style}font-size: 36px;`); 
  19.   } 
  20. }); 

代碼中的 yellowStyle、boldStyle 和 bigSizeStyle 分別是給 print 方法的裝飾器,它們都會(huì)接收 printer,并以 printer 為基礎(chǔ)復(fù)制出一個(gè)一樣的對(duì)象出來(lái)并返回,而返回的 printer 與原來(lái)的區(qū)別是,各自 Decorator 都會(huì)為 printer 的 print 方法加上各自裝飾的邏輯(例如改變字體、顏色或字號(hào))后再調(diào)用 printer 的 print。

使用方式如下:

只要把所有裝飾的邏輯抽出來(lái),就能夠自由的搭配什么時(shí)候要輸出什么樣式,加入要再增加一個(gè)斜體樣式,也只需要再新增一個(gè)裝飾器就行了,不需要改動(dòng)原來(lái)的 print 邏輯。

[[398741]]

不過(guò)要注意的是上面的代碼只是簡(jiǎn)單的把 Object 用解構(gòu)復(fù)制,如果在 prototype 上存在方法就有可能會(huì)出錯(cuò),所以要深拷貝一個(gè)新對(duì)象的話,還需要另外編寫(xiě)邏輯:

  1. const copyObj = (originObj) => { 
  2.   const originPrototype = Object.getPrototypeOf(originObj); 
  3.   let newObj = Object.create(originPrototype); 
  4.     
  5.   const originObjOwnProperties = Object.getOwnPropertyNames(originObj); 
  6.   originObjOwnProperties.forEach((property) => { 
  7.     const prototypeDesc = Object.getOwnPropertyDescriptor(originObj, property); 
  8.      Object.defineProperty(newObj, property, prototypeDesc); 
  9.   }); 
  10.    
  11.   return newObj; 

然后裝飾器內(nèi)改使上面代碼中的 copyObj,就能正確復(fù)制相同的對(duì)象了:

  1. const yellowStyle = (printer) => { 
  2.   const decorator = copyObj(printer); 
  3.  
  4.   decorator.print = (text = ''style = '') => { 
  5.     printer.print(text, `${style}color: yellow;`); 
  6.   }; 
  7.  
  8.   return decorator; 
  9. }; 

其他案例

因?yàn)槲覀冇玫恼Z(yǔ)言是 JavaScript,所以沒(méi)有用到類(lèi),只是簡(jiǎn)單的裝飾某個(gè)方個(gè)方法,比如下面這個(gè)用來(lái)發(fā)布文章的 publishArticle:

  1. const publishArticle = () => { 
  2.   console.log('發(fā)布文章'); 
  3. }; 

如果你想要再發(fā)布文章之后在 微博或QQ空間之類(lèi)的平臺(tái)上發(fā)個(gè)動(dòng)態(tài),那又該怎么處理呢?是像下面的代碼這樣嗎?

  1. const publishArticle = () => { 
  2.   console.log('發(fā)布文章'); 
  3.  
  4.   console.log('發(fā) 微博 動(dòng)態(tài)'); 
  5.   console.log('發(fā) QQ空間 動(dòng)態(tài)'); 
  6. }; 

這樣顯然不好!publishArticle 應(yīng)該只需要發(fā)布文章的邏輯就夠了!而且如果之后第三方服務(wù)平臺(tái)越來(lái)越多,那 publishArticle 就會(huì)陷入一直加邏輯一直爽的情況,在明白了裝飾器模式后就不能再這樣做了!

所以把這個(gè)需求套上裝飾器:

  1. const publishArticle = () => { 
  2.   console.log('發(fā)布文章'); 
  3. }; 
  4.  
  5. const publishWeibo = (publish) => (...args) => { 
  6.   publish(args); 
  7.   console.log('發(fā) 微博 動(dòng)態(tài)'); 
  8. }; 
  9.  
  10. const publishQzone = (publish) => (...args) => { 
  11.   publish(args); 
  12.   console.log('發(fā) QQ空間 動(dòng)態(tài)'); 
  13. }; 
  14.  
  15.  
  16. const publishArticleAndWeiboAndQzone = publishWeibo(publishQzone(publishArticle)); 

前面 Printer 的例子是復(fù)制一個(gè)對(duì)象并返回,但如果是方法就不用復(fù)制了,只要確保每個(gè)裝飾器都會(huì)返回一個(gè)新方法,然后會(huì)去執(zhí)行被裝飾的方法就行了。

總結(jié)

裝飾器模式是一種非常有用的設(shè)計(jì)模式,在項(xiàng)目中也會(huì)經(jīng)常用到,當(dāng)需求變動(dòng)時(shí),覺(jué)得某個(gè)邏輯很多余,那么直接不裝飾它就行了,也不需要去修改實(shí)現(xiàn)邏輯的代碼。每一個(gè)裝飾器都做他自己的事情,與其他裝飾器互不影響。

責(zé)任編輯:趙寧寧 來(lái)源: 前端先鋒
相關(guān)推薦

2021-02-18 15:43:37

Python裝飾器Decorator

2024-08-13 17:56:52

單例裝飾器模式

2019-12-09 09:12:59

程序員年薪裁員

2021-06-17 09:32:17

前端TypeScript 技術(shù)熱點(diǎn)

2020-09-03 07:55:02

并發(fā)操作系統(tǒng)Java

2020-08-04 11:35:38

Vue前端裝飾器

2009-07-22 11:02:54

2021-04-11 07:48:42

定時(shí)任務(wù)Linux jdk

2013-06-20 11:11:00

程序員經(jīng)理

2017-11-09 14:40:49

懸浮Tab代碼

2020-10-19 08:20:44

技術(shù)管理轉(zhuǎn)型

2023-09-04 13:14:00

裝飾器設(shè)計(jì)模式

2020-08-11 10:40:31

裝飾者模式Java組件

2024-01-22 11:48:20

策略模式開(kāi)發(fā)

2020-05-25 09:20:10

職場(chǎng)技能互聯(lián)網(wǎng)

2021-06-11 06:45:32

SQL結(jié)構(gòu)化語(yǔ)言

2021-07-15 06:43:11

Module Fede開(kāi)發(fā)場(chǎng)景

2017-01-10 09:59:51

2014-06-27 18:22:19

2019-07-10 07:59:44

Python編程語(yǔ)言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)