首頁 >web前端 >js教程 >js代理設計模式詳解

js代理設計模式詳解

小云云
小云云原創
2018-02-22 13:22:301543瀏覽

代理模式是常見的設計模式之一,是指不直接呼叫實際的對象,而是透過代理對象,來間接的呼叫實際的對象。

為什麼要採用這種間接的形式來呼叫物件呢?一般是因為客戶端不想直接存取實際的對象,或存取實際的對象存在困難,因此透過一個代理對象來完成間接的存取, 例如請一個律師代理來打官司.

代理設計模式和裝飾設計模式差異

裝飾模式會對被包裝物件的功能進行修改或擴充, 而代理模式只不過控制它的存取.除了會添加一些控制碼, 代理程式不會對本體方法進行修改,裝飾模式為修改方法而生

被包裝物件的創建方式, 裝飾模式被包裝實例化是完全獨立的, 代理模式則是代理的實例過程的一部分, 在虛擬代理中, 這種實例化受嚴格控制, 不允許在內部進行

代理不會像裝飾那樣相互包裝,

結構

js代理設計模式詳解

代理模式中的角色

  • 接口
    聲明了目標類別及代理類別物件的共同接口,這樣在任何可以使用目標物件的地方都可以使用代理物件。

  • 物件類別
    定義了代理物件所代表的目標物件。

  • 代理類別
    代理程式物件內部含有目標物件的引用,從而可以在任何時候操作目標物件;代理物件和目標物件具有統一的接口,以便可以再任何時候替代目標對象。代理物件通常在客戶端呼叫傳遞給目標物件之前或之後,執行某些操作,而非單純的將呼叫傳遞給目標物件。

  • 介面

    /* 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);
      }
    };

相關推薦:

基於Java的代理程式設計模式_MySQL

以上是js代理設計模式詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn