《javascript設計模式》學習筆記七:Javascript面向物件程式設計組合模式詳解
本文例項講述了Javascript面向物件程式設計組合模式。分享給大家供大家參考,具體如下:
概述
關於組合模式的定義:組合模式(Composite Pattern)有時候又叫做部分-整體模式,它使我們樹型結構的問題中,模糊了簡單元素和複雜元素的概念,客戶程式可以向處理簡單元素一樣來處理複雜元素,從而使得客戶程式與複雜元素的內部結構解耦。來自百度百科:http://baike.baidu.com/view/3591789.htm
其實從面向物件之五之後,與javascript本身關係不是很大,更重要的是設計模式的一些概念,只要瞭解javascript面向物件的一般知識,掌握設計模式的含義,程式碼本身並不是很難。
這裡簡單說一下組合模式,其實組合模式就是將一系列相似或相近的物件組合在一個大的物件,由這個大物件提供一些常用的介面來對這些小物件進行操作,程式碼可重用,對外操作簡單。例如對於一個form裡的元素,不考慮頁面設計的情況下,一般就剩下input了,對於這些input都有name和value的屬性,因此可以將這些input元素作為form物件的成員組合起來,form物件提供對外的介面,便可以實現一些簡單的操作,比如設定某個input的value,新增/刪除某個input等等……
正文
介紹:組合模式又叫部分整體模式,用於把一組相似的物件當作一個單一的物件。組合模式依據樹形結構來組合物件,用來表示部分以及整體層次
定義:組合多個物件形成樹形結構以表示具有整體一部分關係的層次機構。組合模式對單個物件(即葉子物件)和組合物件(即容器物件)的使用具有一致性,組合模式又可以成為整體一部分模式。
它是一種物件結構型模式。
場景:我們對公司的人員架構進行一下列印,假設所有管理崗和開發崗的區別只有一個,是不是有下級員工。我們來實現下:
示例:
var LEADER = function(name,dept){ this._name = name || ''; //姓名 this._dept = dept || ''; //職位 this._subordinates = []; //下屬 this.add = function(employee){ this._subordinates.push(employee); } this.remove = function(employee){ this._subordinates.splice(this._subordinates.indexOf(employee),1); } this.getSubordinates = function(){ return this._subordinates; } this.toString = function(){ console.log('姓名:'+this._name+',職位:'+this._dept) } } var JAVARD = function(name,dept){ this._name = name || ''; //姓名 this._dept = dept || ''; //職位 this.toString = function(){ console.log('姓名:'+this._name+',職位:'+this._dept) } } var FERD = function(name,dept){ this._name = name || ''; //姓名 this._dept = dept || ''; //職位 this.toString = function(){ console.log('姓名:'+this._name+',職位:'+this._dept) } } function addData(){ var CEO = new LEADER('spancer','CEO'); var CTO = new LEADER('zijian','CTO'); var MANAGER = new LEADER('jiang','LEADER'); var JAVA_LEADER = new LEADER('fei','JAVA_LEADER'); var FE_LEADER = new LEADER('risker','FE_LEADER'); var wh = new FERD('wanghui','FE'); var si = new FERD('si','FE'); var amy = new FERD('amy','FE'); var wei = new JAVARD('wei','JAVA'); var guo = new JAVARD('guo','JAVA'); var yuan = new JAVARD('yuan','JAVA'); CEO.add(CTO); CTO.add(MANAGER); MANAGER.add(JAVA_LEADER); MANAGER.add(FE_LEADER); FE_LEADER.add(wh); FE_LEADER.add(si); FE_LEADER.add(amy); JAVA_LEADER.add(wei); JAVA_LEADER.add(guo); JAVA_LEADER.add(yuan); return CEO; } var eachEmployee = function(employee){ for(var employ of employee.getSubordinates()){ employ.toString(); if(employ.getSubordinates && employ.getSubordinates().length > 0){ eachEmployee(employ); } } } var CEO = addData(); CEO.toString(); eachEmployee(CEO); // 姓名:spancer,職位:CEO // 姓名:zijian,職位:CTO // 姓名:jiang,職位:LEADER // 姓名:fei,職位:JAVA_LEADER // 姓名:wei,職位:JAVA // 姓名:guo,職位:JAVA // 姓名:yuan,職位:JAVA // 姓名:risker,職位:FE_LEADER // 姓名:wanghui,職位:FE // 姓名:si,職位:FE // 姓名:amy,職位:FE
這裡我們簡單寫的這個demo,用來對公司組織架構進行遍歷輸出。因為rd和leader具體職能的不同,我們把技術和管理分為兩大類。但是這樣的設計存在很多問題:
* 可擴充套件性差,當一個新的職位產生,在對其歸類時是新增一個還是放到已有類目下面都是一個問題。
* 當某一行為發生變化需要挨個修改leader類rd類,不符合開關原則。
接下來我們用組合模式實現下:
var Employee = function(name,職位:'+this._dept) } } function addData(){ var CEO = new Employee('spancer','CEO'); var CTO = new Employee('zijian','CTO'); var LEADER = new Employee('jiang','LEADER'); var JAVA_LEADER = new Employee('fei','JAVA_LEADER'); var FE_LEADER = new Employee('risker','FE_LEADER'); var wh = new Employee('wanghui','FE'); var si = new Employee('si','FE'); var amy = new Employee('amy','FE'); var wei = new Employee('wei','JAVA'); var guo = new Employee('guo','JAVA'); var yuan = new Employee('yuan','JAVA'); CEO.add(CTO); CTO.add(LEADER); LEADER.add(JAVA_LEADER); LEADER.add(FE_LEADER); FE_LEADER.add(wh); FE_LEADER.add(si); FE_LEADER.add(amy); JAVA_LEADER.add(wei); JAVA_LEADER.add(guo); JAVA_LEADER.add(yuan); return CEO; } var eachEmployee = function(employee){ for(var employ of employee.getSubordinates()){ employ.toString(); if(employ.getSubordinates().length > 0){ eachEmployee(employ); } } } var CEO = addData(); CEO.toString(); eachEmployee(CEO); // 姓名:spancer,職位:FE
大家可以對比下兩段程式碼的差異,我們用一個Employee類來替換leader和rd類,其實這就是組合模式的關鍵:
定義一個抽象類,它既可以代表leader也可以代表rd,新增、列印時也基於Employee類,而無需知道這個人是什麼角色。可以對其進行統一處理。
組合模式總結:
優點:
* 可以清楚的定義存在層次關係的複雜物件,讓客戶端開發過程中忽略層次的差異
* 全域性修改時,只需修改一處位置
缺點:
* 無法對生成結果進行限制,不能像第一個例子一樣,所有的rd都沒有下級員工屬性,也沒有對應方法。所以在使用時要注意這些約束
適用場景;
* 在一個面向物件的語言開發系統中需要處理一個樹形結構。
* 在具有整體和部分的結構中,希望忽略掉二者差異,使客戶端一致對待。
感興趣的朋友可以使用線上HTML/CSS/JavaScript程式碼執行工具:http://tools.jb51.net/code/HtmlJsRun測試上述程式碼執行效果。
更多關於JavaScript相關內容感興趣的讀者可檢視本站專題:《javascript面向物件入門教程》、《JavaScript錯誤與除錯技巧總結》、《JavaScript資料結構與演算法技巧總結》、《JavaScript遍歷演算法與技巧總結》及《JavaScript數學運算用法總結》
希望本文所述對大家JavaScript程式設計有所幫助。