代理模式(Proxy)

jdon發表於2019-08-07

目的
為另一個物件提供代理或佔位符以控制對它的訪問。

說明
想象一座塔,當地巫師去那裡學習他們的法術。象牙塔只能透過代理訪問,這確保只有前三個巫師可以進入。這裡的代理代表了塔臺的功能,並新增了訪問控制。
簡而言之,使用代理模式,類表示另一個類的功能。

維基百科說
代理以其最一般的形式,是一個類,充當其他東西的介面。代理是一個包裝器或代理物件,客戶端正在呼叫它以便在後臺訪問真正的服務物件。使用代理可以簡單地轉發到真實物件,或者可以提供額外的邏輯。在代理中,可以提供額外的功能,例如,當對真實物件的操作佔用大量資源時進行快取,或者在呼叫對真實物件的操作之前檢查前提條件。

程式化示例
以我們的巫師塔為例。首先我們有巫師塔介面和象牙塔類

public interface WizardTower {

  void enter(Wizard wizard);
}

public class IvoryTower implements WizardTower {

  private static final Logger LOGGER = LoggerFactory.getLogger(IvoryTower.class);

  public void enter(Wizard wizard) {
    LOGGER.info("{} enters the tower.", wizard);
  }

}


然後是一個簡單的嚮導類

public class Wizard {

  private final String name;

  public Wizard(String name) {
    this.name = name;
  }

  @Override
  public String toString() {
    return name;
  }
}


然後我們有了代理來新增對嚮導塔的訪問控制

public class WizardTowerProxy implements WizardTower {

  private static final Logger LOGGER = LoggerFactory.getLogger(WizardTowerProxy.class);

  private static final int NUM_WIZARDS_ALLOWED = 3;

  private int numWizards;

  private final WizardTower tower;

  public WizardTowerProxy(WizardTower tower) {
    this.tower = tower;
  }

  @Override
  public void enter(Wizard wizard) {
    if (numWizards < NUM_WIZARDS_ALLOWED) {
      tower.enter(wizard);
      numWizards++;
    } else {
      LOGGER.info("{} is not allowed to enter!", wizard);
    }
  }
}


這裡是塔樓進入場景

WizardTowerProxy proxy = new WizardTowerProxy(new IvoryTower());
proxy.enter(new Wizard("Red wizard")); // Red wizard enters the tower.
proxy.enter(new Wizard("White wizard")); // White wizard enters the tower.
proxy.enter(new Wizard("Black wizard")); // Black wizard enters the tower.
proxy.enter(new Wizard("Green wizard")); // Green wizard is not allowed to enter!
proxy.enter(new Wizard("Brown wizard")); // Brown wizard is not allowed to enter!


適用場景
當需要一個比簡單指標更通用或更復雜的物件引用時,代理就適用。下面是代理模式適用的幾種常見情況
  • 遠端代理為不同地址空間中的物件提供本地代理。
  • 虛擬代理按需建立昂貴的物件。
  • 保護代理控制對原始物件的訪問。當物件具有不同的訪問許可權時,保護代理很有用。

典型用例
  • 控制對其他物件的訪問
  • 延遲初始化
  • 實施日誌記錄
  • 方便網路連線
  • 計算對物件的引用

相關文章