為什么要采用這種間接的形式來調(diào)用對象呢?一般是因為客戶端不想直接訪問實際的對象,或者訪問實際的對象存在困難,因此通過一個代理對象來完成間接的訪問, 比如請一個律師代理來打官司.
代理設(shè)計模式和裝飾設(shè)計模式區(qū)別
裝飾模式會對被包裝對象的功能進(jìn)行修改或擴充, 而代理模式只不過控制它的訪問.除了會添加一些控制代碼, 代理不會對本體方法進(jìn)行修改, 裝飾模式為修改方法而生
被包裝對象的創(chuàng)建方式, 裝飾模式被包裝實例化是完全獨立的, 代理模式則是代理的實例過程的一部分, 在虛擬代理中, 這種實例化受嚴(yán)格控制, 不許在內(nèi)部進(jìn)行
代理不會像裝飾那樣相互包裝,
結(jié)構(gòu)
代理模式中的角色
接口
聲明了目標(biāo)類及代理類對象的共同接口,這樣在任何可以使用目標(biāo)對象的地方都可以使用代理對象。對象類
定義了代理對象所代表的目標(biāo)對象。代理類
代理對象內(nèi)部含有目標(biāo)對象的引用,從而可以在任何時候操作目標(biāo)對象;代理對象和目標(biāo)對象具有統(tǒng)一的接口,以便可以再任何時候替代目標(biāo)對象。代理對象通常在客戶端調(diào)用傳遞給目標(biāo)對象之前或者之后,執(zhí)行某些操作,而非單純的將調(diào)用傳遞給目標(biāo)對象。接口
var Library = new Interface('Library', ['findBooks', 'checkoutBook', 'returnBook']);
對象類
var PublicLibrary = function(books) { // implements Library this.catalog = {}; for(var i = 0, len = books.length; i < len; i++) { this.catalog[books[i].getIsbn()] = { book: books[i], available: true }; } }; PublicLibrary.prototype = { findBooks: function(searchString) { var results = []; for(var isbn in this.catalog) { if(!this.catalog.hasOwnProperty(isbn)) continue; if(searchString.match(this.catalog[isbn].getTitle()) || searchString.match(this.catalog[isbn].getAuthor())) { results.push(this.catalog[isbn]); } } return results; }, checkoutBook: function(book) { var isbn = book.getIsbn(); if(this.catalog[isbn]) { if(this.catalog[isbn].available) { this.catalog[isbn].available = false; return this.catalog[isbn]; } else { throw new Error('PublicLibrary: book ' + book.getTitle() + ' is not currently available.'); } } else { throw new Error('PublicLibrary: book ' + book.getTitle() + ' not found.'); } }, returnBook: function(book) { var isbn = book.getIsbn(); if(this.catalog[isbn]) { this.catalog[isbn].available = true; } else { throw new Error('PublicLibrary: book ' + book.getTitle() + ' not found.'); } } };
代理類
var PublicLibraryProxy = function(catalog) { // implements Library this.library = new PublicLibrary(catalog); }; PublicLibraryProxy.prototype = { findBooks: function(searchString) { return this.library.findBooks(searchString); }, checkoutBook: function(book) { return this.library.checkoutBook(book); }, returnBook: function(book) { return this.library.returnBook(book); } };
PublicLibraryProxy與PublicLibrary實現(xiàn)率同樣的接口, 通過組合方式將后者一對象作為事例, 當(dāng)調(diào)用對象方法時, 會通過這個屬性調(diào)用事例的方法, 這種方式和裝飾設(shè)計模式類似,
然而這種沒有任何訪問控制的代理的做法并沒有什么用處, 在各種其他的代理中虛擬代理是最有用的, 至于為什么可以參考 Jabascript設(shè)計模式 這本書,
虛擬代理用于控制對那種創(chuàng)建開銷很大的本體的訪問, 他會將本體的實例化推遲到有方法被調(diào)用的時候--懶加載,
虛擬代理類
var PublicLibraryVirtualProxy = function(catalog) { // implements Library this.library = null; this.catalog = catalog; // Store the argument to the constructor. }; PublicLibraryVirtualProxy.prototype = { _initializeLibrary: function() { if(this.library === null) { this.library = new PublicLibrary(this.catalog); } }, findBooks: function(searchString) { this._initializeLibrary(); return this.library.findBooks(searchString); }, checkoutBook: function(book) { this._initializeLibrary(); return this.library.checkoutBook(book); }, returnBook: function(book) { this._initializeLibrary(); return this.library.returnBook(book); } };
相關(guān)推薦:
基于Java的代理設(shè)計模式_MySQL
以上就是js代理設(shè)計模式詳解的詳細(xì)內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!