子慕談設計模式系列(一)

2022-01-10 15:02:12 字數 3594 閱讀 6781

設計模式不容易用文字描述清楚,而過多的**,看起來也讓人摸不到頭腦,加上詞語或者文字描述的抽象感,很容易讓人看了無數設計模式的文章,也仍然理解不了。  所以我一直打算寫此系列部落格,首先我會從大量文章裡去理解這些設計模式,最後我用自己的語言組織轉化為部落格,希望用更少的**,更容易理解的文字,來聊一聊這些設計模式。  我所理解、所描述的每乙個設計模式也可能有些是錯誤的,甚至也不一定有非常深刻的理解,所以希望有人指出,我可以更改部落格內容。  因為我是前端,所以設計模式的**以前端**和視角為主。  此部落格內容對每一種模式並不會寫得非常深入,也許能為讀者打通一些認知,如果看了此系列部落格,再去看其他更深入的部落格,可能是一種比較好的方式。

單例是保證乙個類只建立乙個例項,例項不存在新建乙個例項,例項存在返回已經存在的例項。  單例模式很好理解,使用情況也很多,比如我最近做的ng4的專案,會定義一些service(ng的service都是單例),service裡面存放的資料供全域性使用,所有元件共享這個service。  

再說乙個應用例項: 全域性toast框,我們只需要每次呼叫同乙個例項改變toast框裡的文字,並控制其隱藏顯示。

下面是書中工廠模式的例子,關於它的實現和優劣我就不說了,這裡只是以個人的理解來說為什麼它叫工廠模式。  建立物件的時候,都會先新建乙個新的原生物件,再對它進行屬性賦值,最後返回乙個成品物件。所有屬性和方法都在它內部,都是它唯一擁有的。那麼傳統工廠生產出來的電視手機等這些硬體,他們就是這種模式,他們的在出廠前就會在產品內部定義好所有的元件,最後加工為成品。所以我們就這樣來理解工廠模式的命名吧。

function

createperson(name, age, job);

returno;}

var person1 = createperson("nicholas", 29, "software engineer");

var person2 = createperson("greg", 27, "doctor");

使用多個簡單的物件一步一步構建成乙個複雜的物件。它使組裝過程和每個部件的開發分離開來。

直接舉個例子: 假如我們要設計乙個h5飛機遊戲,那麼我們設計一款飛機的前端**,把飛機先簡單拆分為如下兩個部件: 機體、子彈。每個部件定義乙個物件,然後設定它們的引數(比如飛機位址,子彈設定傷害100的威力值和子彈位址),最後通過組裝**邏輯來組裝成一架完整的遊戲飛機。 那麼飛機是乙個複雜物件,這兩個部件就是更單純更簡單的物件。來點**示例:

function

plane()

plane.prototype =

},buildbulletmodule:

function

()}}

當需求變動的時候,我們只需修改對應的單個部件,甚至可以隨時在移除或者新增其它部件。 所以這樣我們就大致能理解為什麼它叫建造者模式了,現實生活中,乙個複雜工程,就比如汽車、建築、飛機等,他們都是由不同的精細設計的部件通過合理的組裝才生產出成品的。  建造者模式和裝飾者模式看起來實際有點類似,下面就說裝飾者模式。

裝飾模式指的是在不必改變原類檔案和使用繼承的情況下,動態地擴充套件乙個物件的功能。它是通過建立乙個包裝物件,也就是裝飾來包裹真實的物件。  其實裝飾者模式就是通過乙個特定的方法,給乙個例項物件新增特定的功能。比如乙個基礎汽車類,有引擎、輪胎和車架,**如下:

function basecar(){}

basecar.prototype =

我們在車的基礎上,貼一些裝飾紙,以下**就是最基礎的裝飾者模式的使用。

var car = new

basecar();

setstyle(car);

setstyle(carobj)

所謂裝飾者模式,就是通過乙個外部的方法,來包裝乙個物件,並且擴充套件它。

實際裝飾者模式和建造者模式,都有類似分步的方式去建立乙個物件。而建造者模式是在類的內部,一步步建造物件,很強調整體性和邏輯性,當然我上面的例子並沒有體現邏輯性之說,如果我們把飛機的機體再拆分一下,我們可能需要先建立機體的機艙(),再根據機艙位置,放置或者說定位側翼和尾翼位置,那麼這就是所謂邏輯性了。  而裝飾者模式,是傳入物件到外部函式,通過函式體內部對物件進行擴充套件。其實通過外部函式,也能達到邏輯性的要求,通過外部函式的多次呼叫,讓物件新增和迭代功能。但是如果所有的組裝過程都是通過外部函式進行,在物件屬性和子物件的引用上可能會讓**變得非常複雜,甚至可能需要函式裡返回物件,再用另乙個函式包裹這類的函式巢狀,整體的邏輯從**層面看來也會變得複雜和難以理解。  對於裝飾者模式的使用,還是應該如它的名字一樣,就應該是為乙個基礎功能完整的物件新增一些額外的擴充套件。  在物件導向程式設計的程式裡,建造者模式和裝飾者模式應該是常會結合在一起使用,把上面的汽車例子,改編成乙個更像這兩模式結合的**:

function

basecar()

basecar.prototype =,

buildengine:

function

(), buildtyre:

function()}

var car = new

basecar();

setstyle(car);

setstyle(carobj)

看了這個圖實際還不能徹底對它進行定性,當我再看到下面的**示例的時候,我就徹底清楚了外觀模式的定義:

function

subsystemone()

function

subsystemtwo()

function

subsystemthree()

facade()

外觀模式是把一系列邏輯封裝到乙個方法中,使當前邏輯更易使用,更易維護。那麼我們實際前端開發中,會常常用到,說乙個前端開發中的例子: 乙個後台管理系統,有乙個使用者列表頁面,新增使用者和修改使用者資訊,觸發新增或者修改按鈕的時候,都是使用的同乙個彈窗模板,然後根據不同的傳參去判斷是否是新增或者修改,再去改變彈框模板表單裡的資料,新增的時候所有表單為空,編輯的時候把之前資料載入到表單。那麼這個彈窗模板就是門面、也就是上圖的facade。表單的html**是不變的,沒有必要寫兩個模板,所以這也可以叫**去重。

再舉乙個例子: 上面說的彈框模板的表單,在新增使用者成功的**函式裡我們需要把表單裡的資料給重置了,**如下:

adduser())

}

adduser())

}edituser())

}function

reset()

reset方法就是facade,甚至說有更複雜的需求的時候,reset方法還可以傳引數,根據引數來重置某幾個表單,總之reset方法把重置表單的邏輯封裝在此方法內,其他地方需要呼叫重置相關功能,都用經過它才行,這樣可以減少**的耦合性,去除很多重複**,後期維護也非常清晰、改動也方便。  jq的 $ 選擇器,其實也是此模式,它專門處理dom選擇,集合了id、class等等選擇器,我們只需要在傳引數的時候前面加上#或者.,$('#id'),$('.class'),就能選擇相應的dom。

淺淺一談 設計模式

看軟體設計資料,走到設計模式這裡,一頭霧水。遂翻書學習,這裡簡單記錄一下,為以後複習用 1,簡單工廠 簡單工廠 寫乙個計算 加減乘除的運算 1 class program218 1920 21 運算類22 23 class operationclass 2430 set 31 32private d...

談C 設計模式

談 c 設計模式 這裡我只談單件和工廠。a 單件singleton,它允許乙個類有且只有乙個例項的方法。也就是說類的實體只有1個。example singleton include using namespace std class singleton singleton operator cons...

初談設計模式

簡介 現在模式設計從很早之前的面相過程的原則到現在的面相物件的原則 object oriented簡稱oo 設計模式在軟體開發過程中是個必不可少的知識點。或許許多剛開始編寫 或沒有維護過產品的人很少體驗過設計模式的重要性,但是運用恰當的設計模式,能極大減少需求變更的代價和 重構的風險。大綱使用模式的...