摘要:注意事項聲明函數時候處理業務邏輯區分和單例的區別,配合單例實現初始化構造函數大寫字母開頭推薦注意的成本。簡單工廠模式使用一個類通常為單體來生成實例。
@(書籍閱讀)[JavaScript, 設計模式]
常見設計模式一直對設計模式不太懂,花了一下午加一晚上的時間,好好的看了看各種設計模式,并總結了一下。
設計模式簡介設計模式概念解讀
設計模式的發展與在JavaScript中的應用
設計原則
設計模式概念解讀設計模式(Design pattern):
>是一套被反復使用,思想成熟,經過分類和無數實戰設計經驗的總結。使用設計模式是為了讓系統代碼可重用,可擴展,可解耦,更容易被人理解且能保證代碼可靠性。設計模式使代碼開發真正工程化;設計模式是軟件工程的基石脈絡,如同大廈的結構一樣。只有夯實地基搭好結構,才能蓋出堅壯的大樓。也是我們邁向高級開發人員必經的一步。
一層書柜--》兩層書柜--》各種書柜分門別類
設計模式的發展與在JavaScript中的運用四人幫的書,設計模式的圣經Gof
編程語言之間是想通的;
很多本該有的東西JavaScript都有,但是并沒有作為正式的部分。這些年人們利用自己對計算機編程的思想,利用了很多晦澀的技巧實現了很多JavaScript設計者都未曾預計到的任務,比如各種設計模式的實現,比如面向對象的編程。
設計模式的根本原因是為了代碼復用,增加可維護性。有如下原則:
【開閉原則】:對擴展開放,對修改關閉;
【里氏轉換原則】:子類繼承父類,多帶帶調用完全可以運行;
【依賴倒轉原則】:引用一個對象,如果這個對象有底層類型,直接引用底層;
【結構隔離原則】:每一個接口應該是一種角色;
【合成/聚合復用原則】:新對象應該使用一些已有的對象,使之成為新對象的一部分;
【迪米特原則】:一個對象應該對其它對象有盡可能少的了解;
站在巨人的肩膀上整體HOLD系統架構。
單例就是保證一個類只有一個實例,實現的方法一般是先判斷實例存在與否,如果存在則直接返回,如果不存在就創建了再返回,這就確保了一個類只有一個實例對象。
在JavaScript中,單例作為一個命名空間提供者,從全局命名空間里提供一個唯一的訪問點來訪問該對象。
比如說一座房子只有一扇門,有一扇門就不用再開門了,如果沒有門則需要創建一個門。每個門都只屬于一個戶主(命名空間),門是戶與戶之間的唯一接口,你要來我家,只能從這個門進來。
命名空間:
單例模式作用和注意事項通常來說,命名空間是唯一識別的一套名字,這樣當對象來自不同的地方但是名字相同的時候就不會含糊不清了。
模塊間通信;
系統中某個類的對象只能存在一個;
保護自己的屬性和方法(不受外面的干擾);
注意this的使用:隨著調用不斷變化,誰調用指向誰;
閉包容易造成內存泄露,不需要的趕快干掉:閉包就是拿到不該拿到的東西,return;
注意new的成本。(繼承)
單例模式代碼實戰和總結var single = (function() { var unique; function getInstance() { if (unique === undefined) { unique = new Construct(); } return unique; } function Construct() { // ... 生成單例的構造函數的代碼 } return { getInstance: getInstance } })();構造函數模式 構造模式概念解讀
構造函數用于創建特定類型的對象-不僅聲明了使用的對象,構造函數還可以接收參數以便第一次創建對象的時候設置對象的成員值。可以自定義構造函數,然后在里面聲明自定義類型對象的屬性和方法;
在JavaScript里,構造函數通常是認為用來實現實例的,JavaScript沒有類的概念,但是有特殊的構造函數。通過new關鍵字來調用自定義的構造函數,在構造函數內部,this關鍵字引用的是新創建的對象。
每家都有一個門,但是每個門都有自己的特點,可以根據自己的需要添加不同的特點(傳入不同的值)。
構造模式作用和注意事項用于創建特點類型的對象:給某一個人
第一次聲明的時候給對象賦值;
自己聲明構造函數,賦予屬性和方法;(告訴別人自己想要怎么樣的門。)
聲明函數時候處理業務邏輯;
區分和單例的區別,配合單例實現初始化;
構造函數大寫字母開頭(推薦~)
注意new的成本。(繼承)(相同的盡量放在原型鏈上)
構造模式實戰與總結最簡單的構造函數:
function Car(model, year, miles) { this.model = model; this.year = year; this.miles = miles; this.output= function () { return this.model + "走了" + this.miles + "公里"; }; } var tom= new Car("大叔", 2009, 20000); var dudu= new Car("Dudu", 2010, 5000); console.log(tom.output()); console.log(dudu.output());
強制使用new的方法:
function Car(model, year, miles) { if (!(this instanceof Car)) { return new Car(model, year, miles); } this.model = model; this.year = year; this.miles = miles; this.output = function () { return this.model + "走了" + this.miles + "公里"; } } var tom = new Car("大叔", 2009, 20000); var dudu = Car("Dudu", 2010, 5000); console.log(typeof tom); // "object" console.log(tom.output()); // "大叔走了20000公里" console.log(typeof dudu); // "object" console.log(dudu.output()); // "Dudu走了5000公里"建造者模式 建造者模式概念解讀
建造者模式可以將一個復雜對象的構建與其表示相分離,使得同樣的構建過程可以創建不同的表示。也就是說,如果我們用了建造者模式,那么用戶就需要指定需要建造的類型就可以得到它們,而具體建造的過程和細節就不需要知道了。建造者模式實際,就是一個指揮者,一個建造者,一個使用指揮者調用具體建造者工作得出結果給客戶。
建造者模式主要用于“分步驟構建一個復雜的對象”,“分步驟”是一個穩定的算法,而復雜對象的各個部分則經常變化。
說一戶家人要建房子,但房子主人或家里其他人是不懂得如何去建房子的,所以他得去請幾個工人,這個建房子的隊伍還得有個工頭,來按房主人的想法來建一套房子,工頭按房主人的要求設計要求工人如何如何做;
工頭說,第一步先把房整體骨架搭起來,第二步睡房建造好,第三步把廚房裝飾好,第四步把客廳建造裝飾完畢,第五步...
工頭是不做事的,但具體建造者必須按照工頭的要求來做,第一步,第二步的這樣步驟來建造,直至整個房子完成;
創建者必須要有創建這個房屋的所有技能,即建骨架,裝飾睡房等...,即建造者所做的事,或所具有的能力,必須大于或等于指揮者要求要做的事,或具有的能力;
即指揮者是個組織者,而建造者提供技能;
建造者模式作用和注意事項模式作用:
分布構建一個復雜的對象(包工頭對工人,工人對房子);
解耦封裝過程和具體構建的組件;
無需關心組件如何組裝;
各司其職,拆解流程;
注意事項:
一定要有一個穩定的算法進行支持(合同);
加工工藝是暴露的(可以直接找工人,但是包工頭更熟悉);
建造者模式代碼實戰和總結工人建造者X:
function workerBuilder() { this.workOne = function() { //建房子骨架 } this.workTwo=function() { //建睡房 } this.workThree=function() { //建廚房 } this.workFour=function() { //建客廳 } //.... this.getResult = function() { //建成房子 var house = new House(); //house.HouseFrame ... return house; } }
workBuilder 是具體建造者類,workOne, Two是要做的事情,建骨架等;
當然 workBuilder 可以多建幾個,用于表示 工人 對于每個工作執行的方法不一樣;但工作內容是一樣的;
指揮者類
function Director() { this.construct = function(builder) { builder.workOne(); builder.workTwo(); builder.workThree(); builder.workFour(); //... //上面的內容,順序可設置,并且工作項也可以設定 } }
指揮者類下的 指導 方法,有對 建造者 的回調引用,內容包括建者工作內容幾項或全部; 指揮者對建造者工人要做的事情進行組織跟安排;
產品房子
function House() { this.HouseFrame = ""; this.Room = ""; this.Kitchen = ""; this.LivingRoom = ""; //... }
使用方法
var builder = new workBuilder(); var director = new Director(); director.construct(builder); var house = builder.getResult();
第四步,整個使用相當于客戶:房主人,房主人請 Director 工頭來建房子,但是工頭是不做事的,所以他指揮 builder 工個來建子,最后房主人從工人那里取得建好的房子;
工廠模式 工廠模式概念解讀工廠模式定義了一個用于創建對象的接口,這個接口決定了實例化哪一個類。該模式使一個類的實例化延遲到了子類。而子類可以重寫接口方法以便創建的時候指定自己的對象類型(抽象工廠)。(簡單工廠:能找到具體細節);抽象工廠只留口,不做事,留給外界覆蓋;
這個模式十分有用,尤其是創建對象的流程賦值的時候,比如依賴于很多設置文件等。并且,會經常在程序里看到工廠方法,用于讓子類定義需要創建的對象類型。
簡單工廠模式:使用一個類(通常為單體)來生成實例。
復雜工廠模式:使用子類來決定一個成員變量應該是哪個具體的類的實例。
廠里可以做衣服可以做鞋,按訂單來生產那種東西,通過廠長安排那條產品線,外界可以修改產品線工藝(抽象工廠)。廠長只是告訴做什么事,
工廠模式的作用和注意事項作用:
對象的構建十分復雜;
需要依賴具體的環境創建不同實例;
處理大量具有相同屬性的小對象;
注意事項:
不能濫用工廠,有時候僅僅是給代碼增加復雜度;
工廠模式代碼實戰簡單工廠模式:
var BicycleFactory = { createBicycle : function( model ){ var bicycle; switch( model ){ case "The Speedster": bicycle = new Speedster(); break; case "The Lowrider": bicycle = new Lowrider(); break; case "The Cruiser": default: bicycle = new Cruiser(); break; } return bycicle; } }
BicycleFactory 是一個脫離于BicycleShop的單體。降低耦合度的效果顯而易見。當需要添加新的類型的時候,不需要動 BicycleShop 只需修改工廠單體對象就可以。
var BicycleShop = function(){}; BicycleShop.prototype = { sellBicycle : function( model ){ var bicycle = BicycleFactory.createBicycle(model); return bicycle; } }
工廠模式:
真正的工廠模式與簡單工廠模式相比,主要區別就是它不是另外使用一個對象或者類來創建實例(自行車),而是使用一個子類。工廠是一個將其成員對象的實例化推遲到子類中進行的類。
比如加入BicycleShop可以決定從那一家廠商進行進貨,那么簡單的一個BicycleFactory是不夠了的,因為各個廠商會各自生產不同的Speedster,Lowrider,Cruiser等型號自行車,所以首先需要生成各自廠商的shop實例,不同廠商的shop實例擁有不同的生成幾個型號自行車的方法。
也就是相當于將自行車對象的實例化推遲到了shop實例中產生。
基礎:
var BicycleShop = function(){} BicycleShop.prototype={ sellBicycle: function( model ){ var bicycle = this.createBicycle( model ); return bicycle; }, createBicycle: function( model ){ throw new Error( " Unsupported " ); } }
各自廠商:
var AcmeBicycleShop = function(){}; extend( AcmeBicycleShop , BicycleShop ); AcmeBicycleShop.prototype.createBicycle = function( model ){ var bicycle; switch( model ){ case "The Speedster": bicycle = new AcmeSpeedster(); break; case "The Lowrider": bicycle = new AcmeLowrider(); break; case "The Cruiser": default: bicycle = new AcmeCruiser(); break; } return bicycle; } var GeneralBicycleShop = function(){}; extend( GeneralBicycleShop , BicycleShop ); GeneralBicycleShop.prototype.createBicycle = function( model ){ ... }
那么接下來就很簡單 對于來自 Acme 進貨的
var acmeShop = new AcmeBicycleShop(); var newBicycle = acmeShop.sellBicycle("The Speedster");
當然,你也可以對于外層生成的子類實例在使用簡單工廠模式進行包裝一下~對于添加其他廠商也很簡單,在創建一個Bicycle的子類重新定義其createBicycle的工廠方法即可。
工廠模式使用場合動態實現
例如自行車的例子,創建一些用不同方式實現統一接口的對象,那么可以使用一個工廠方法或者簡單工廠對象來簡化實現過程。選擇可以是明確進行的也可以是隱含的。
節省設置開銷
如果對象要進行復雜的并且彼此相關的設置的時候,那么工廠模式可以很顯著的減少每種對象的代碼量。將特定的設置代碼提取出來會使得代碼有極大地提升。并且能優化結構便于維護。
用于許多小型對象組成一個大對象。
工廠模式之利
主要好處就是可以消除對象間的耦合,通過使用工程方法而不是new關鍵字。將所有實例化的代碼集中在一個位子防止代碼重復。
工廠模式之弊
大多數類最好使用new關鍵字和構造函數,可以讓代碼更加簡單易讀。而不必去查看工廠方法來知道。
代理:顧名思義就是幫組別人做事,GoF對代理模式的定義如下:
代理模式(Proxy),為其它對象提供一種代理以控制對這個對象的訪問。代理模式是的代理對象控制具體對象的引用。代理幾乎可以是任何對象:文件,資源,內存中的對象,或者是一些難以復制的東西。
中介
經理把收集日報周報反饋給大老板;
卡扣通過中間的黃色東西連接在一起;
代理模式作用和注意點模式作用:
遠程代理(一個對象將不同空間的對象進行局部代理);
虛擬代理(根據需要創建開銷很大的對象如渲染網頁暫時用占位符替代真圖);
安全代理(控制真實對象的訪問權限);
智能指引(調用對象代理處理另外一些事情如垃圾回收機制);
注意事項:
不能濫用代理,有時候僅僅是給代碼增加復雜度;
代理模式實戰代理模式需要三方:
小v和狼貓有點誤會,由大熊君幫著緩和一下誤會慢慢解除了。
function XiaoV(){ this.talk = function(){ console.log("狼貓老弟,不好意思上次的事,請多多諒解。") ; } ; } ; function LangMao(){ this.bb = new BigBear() ; this.talk = function(){ console.log("大熊君好啊,最忌忙什么那?") ; this.bb.talk() ; } ; } ; function BigBear(){ this.xiaov = new XiaoV() ; this.talk = function(){ console.log("狼貓兄弟,中午沒事一起吃頓飯聊聊天,那天我見到小v了,他優化和你說。。。。。。") ; this.xiaov.talk() ; } ; } ; function go(){ new LangMao().talk() ; } ;
抽象角色:聲明真實對象和代理對象的共同接口。
代理角色:代理對象角色內部含有對真實對象的引用,從而可以操作真實對象,同時代理對象提供與真實對象相同的接口以便在任何時刻都能代替真實對象。同時,代理對象可以在執行真實對象操作時,附加其他的操作,相當于對真實對象進行封裝。
真實角色:代理角色所代表的真實對象,是我們最終要引用的對象。
代理模式的一個好處就是對外部提供統一的接口方法,而代理類在接口中實現對真實類的附加操作行為,從而可以在不影響外部調用情況下,進行系統擴展。也就是說,我要修改真實角色的操作的時候,盡量不要修改他,而是在外部在“包”一層進行附加行為,即代理類。
當我們需要使用的對象很復雜或者需要很長時間去構造,這時就可以使用代理模式(Proxy)。例如:如果構建一個對象很耗費時間和計算機資源,代理模式(Proxy)允許我們控制這種情況,直到我們需要使用實際的對象。一個代理(Proxy)通常包含和將要使用的對象同樣的方法,一旦開始使用這個對象,這些方法將通過代理(Proxy)傳遞給實際的對象。 一些可以使用代理模式(Proxy)的情況:
一個對象,比如一幅很大的圖像,需要載入的時間很長。
一個需要很長時間才可以完成的計算結果,并且需要在它計算過程中顯示中間結果
一個存在于遠程計算機上的對象,需要通過網絡載入這個遠程對象則需要很長時間,特別是在網絡傳輸高峰期。
一個對象只有有限的訪問權限,代理模式(Proxy)可以驗證用戶的權限
命令模式 概念解讀命令模式(Command):
用來對方法調用進行參數化處理和傳送,經過這樣處理過的方法調用可以在任何時候執行。也就是說該模式旨在將函數的調用,請求和操作封裝成一個單一的對象,然后對這個對象進行一系列的處理。它也可以用來消除調用操作的對象和實現操作的對象之間的耦合。這為各種具體的類的更換帶來了極大的靈活性。
模式作用:
將函數的封裝,請求,調用結合為一體;
調用具體的函數解耦命令對象和接收對象;
提高程序模塊的靈活性;
注意事項:
不需要借口一致,直接調用函數即可,以免造成浪費;
實戰// 命令
var CreateCommand = function( receiver ){ this.receiver = receiver; } CreateCommand.prototype.execute = function() { this.receiver.action(); }
// 接收者 電視
var TVOn = function() {} TVOn.prototype.action = function() { alert("TVOn"); }
// 接收者 電視
var TVOff = function() {} TVOff.prototype.action = function() { alert("TVOff"); }
// 調用者 遙控器
var Invoker = function( tvOnCommand, tvOffCommand ) { this.tvOnCommand = tvOnCommand; this.tvOffCommand = tvOffCommand; } Invoker.prototype.tvOn = function() { this.tvOnCommand.execute(); } Invoker.prototype.tvOff = function() { this.tvOffCommand.execute(); }
執行Client
var tvOnCommand = new CreateCommand( new TVOn() ); var tvOffCommand = new CreateCommand( new TVOff() ); var invoker = new Invoker( tvOnCommand, tvOffCommand ); invoker.tvOn(); invoker.tvOff();參考文獻
深入理解JavaScript系列(26):設計模式之構造函數模式
[設計模式] javascript 之 建造者模式
JS設計模式二:工廠模式
大熊君說說JS與設計模式之------代理模式Proxy
【JS設計模式】命令模式
極客學院《JS設計模式》系列視頻
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78837.html
摘要:前言是瀏覽器的內置腳本語言。避免,在結構生成之前調用節點,而產生錯誤 前言 JavaScript是瀏覽器的內置腳本語言。當網頁中嵌入了JavaScript腳本,瀏覽器加載網頁時,就會執行腳本,從而操作瀏覽器,實現各種動態效果 JavaScript代碼嵌入網頁的方法 1、元素直接嵌入代碼 function sayHello() { alert(hello!); ...
摘要:前言是瀏覽器的內置腳本語言。避免,在結構生成之前調用節點,而產生錯誤 前言 JavaScript是瀏覽器的內置腳本語言。當網頁中嵌入了JavaScript腳本,瀏覽器加載網頁時,就會執行腳本,從而操作瀏覽器,實現各種動態效果 JavaScript代碼嵌入網頁的方法 1、元素直接嵌入代碼 function sayHello() { alert(hello!); ...
摘要:如果存在一個同名的全局變量,這個全局變量也不會被重寫,除非同名的局部變量被聲明時使用關鍵字。 博客原文地址:Claiyre的個人博客 https://claiyre.github.io/博客園地址:http://www.cnblogs.com/nuannuan7362/如需轉載,請在文章開頭注明原文地址------------------------------------------...
閱讀 2989·2023-04-25 21:23
閱讀 3022·2021-09-22 15:24
閱讀 862·2019-08-30 12:55
閱讀 2095·2019-08-29 18:42
閱讀 2607·2019-08-29 16:27
閱讀 943·2019-08-26 17:40
閱讀 2173·2019-08-26 13:29
閱讀 2604·2019-08-26 11:45