代理模式是常見的設計模式之一,是指不直接呼叫實際的對象,而是透過代理對象,來間接的呼叫實際的對象。
為什麼要採用這種間接的形式來呼叫物件呢?一般是因為客戶端不想直接存取實際的對象,或存取實際的對象存在困難,因此透過一個代理對象來完成間接的存取, 例如請一個律師代理來打官司.
代理設計模式和裝飾設計模式差異
裝飾模式會對被包裝物件的功能進行修改或擴充, 而代理模式只不過控制它的存取.除了會添加一些控制碼, 代理程式不會對本體方法進行修改,裝飾模式為修改方法而生
被包裝物件的創建方式, 裝飾模式被包裝實例化是完全獨立的, 代理模式則是代理的實例過程的一部分, 在虛擬代理中, 這種實例化受嚴格控制, 不允許在內部進行
代理不會像裝飾那樣相互包裝,
接口
聲明了目標類別及代理類別物件的共同接口,這樣在任何可以使用目標物件的地方都可以使用代理物件。
物件類別
定義了代理物件所代表的目標物件。
代理類別
代理程式物件內部含有目標物件的引用,從而可以在任何時候操作目標物件;代理物件和目標物件具有統一的接口,以便可以再任何時候替代目標對象。代理物件通常在客戶端呼叫傳遞給目標物件之前或之後,執行某些操作,而非單純的將呼叫傳遞給目標物件。
介面
/* Library interface. */ var Library = new Interface('Library', ['findBooks', 'checkoutBook', 'returnBook']);
物件類別
/* PublicLibrary class. */ 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實現率同樣的介面, 透過組合方式將後者一物件作為事例, 當呼叫物件方法時, 會透過這個屬性呼叫事例的方法, 這種方式和裝飾設計模式類似,
然而這種沒有任何存取控制的代理程式的做法並沒有什麼用處, 在各種其他的代理中虛擬代理是最有用的, 至於為什麼可以參考Jabascript設計模式 這本書,
虛擬代理用於控制對那種創建開銷很大的本體的訪問, 他會將本體的實例化推遲到有方法被調用的時候--懶加載,
虛擬代理類別
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); } };
相關推薦:
以上是js代理設計模式詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!