1. 程式人生 > >設計模式 —— 代理模式(Proxy Pattern)

設計模式 —— 代理模式(Proxy Pattern)

代理模式(Proxy Pattern)

概念:

定義:代理模式 為另一個物件提供一個替身或佔位符以控制這個物件的訪問。

代理模式很好理解,在生活中也很常見。舉個簡單的例子,我們自己能做很多事情(動作),比如寫作業,出去玩等。當我們和父母在家的時候,同學叫我們出去玩,父母先收到訊息,然後忽略掉出去玩的資訊。如果同學叫我們去寫作業,父母接收到後在傳達給我們。此時父母就是我們的代理,並且對我們 資源 進行了一定的控制,這是代理模式的一種:保護代理

使用代理模式建立代表物件,讓代表物件控制某物件的訪問,被代理的物件可以是 遠端的物件建立開銷大的物件需要安全控制 的物件。

常見的代理模式有 3 種:

遠端代理:控制訪問遠端物件。

虛擬代理:控制訪問建立開銷大的資源。

保護代理:基於許可權控制對資源的訪問。

組成:

代理模式

Subject(介面):Proxy 和 RealSubject 物件都實現 Subject 介面,這使得任何客戶端都可以像處理 Proxy 一樣處理 RealSubject。

Proxy(代理物件):代理物件持有 RealSubject(真實物件)的引用,必要時可以將請求轉發給 Subject。

RealSubject(真實物件):真實物件通常是真正做事情的物件,Proxy 可以控制對 RealSubject 物件的訪問。

例子:

現在有一位明星,他有很多個人資訊,而他的經紀人就是他的代理。經紀人會隱藏很多明星的資訊,如年齡、身高等。

代理模式例子

介面類:包含明星和代理都要實現的方法。

public interface PersonBean {
    String getName();
    String getInteresters();
    int getAge();
    double getHeight();

    void setName(String name);
    void setInteresters(String interesters);
    void
setAge(int age); void setHeight(int height); }

明星類:

public class Star implements PersonBean {
    private String name;
    private String interesters;
    private int age;
    private double height;

    public String getName() {
        return name;
    }

    public String getInteresters() {
        return interesters;
    }

    public int getAge() {
        return age;
    }

    public double getHeight() {
        return height;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setInteresters(String interesters) {
        this.interesters = interesters;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setHeight(int height) {
        this.height = height;
    }
}

經紀人類:

public class ProxyPeoson implements PersonBean{
    private PersonBean star;

    public ProxyPeoson(PersonBean star) {
        this.star = star;
    }

    public String getName() {
        return star.getName();
    }

    public String getInteresters() {
        return star.getInteresters();
    }
    //修改明星的年齡
    public int getAge() {
        return star.getAge()-5;
    }
    //修改明星的身高
    public double getHeight() {
        return star.getHeight()+10;
    }

    public void setName(String name) {
        star.setName(name);
    }

    public void setInteresters(String interesters) {
        star.setInteresters(interesters);
    }

    public void setAge(int age) {
        star.setAge(age);
    }

    public void setHeight(int height) {
        star.setHeight(height);
    }
}

測試類:

public class ProxyTest {
    public static void main(String[] args) {
        Star star = new Star();
        ProxyPeoson proxyPeoson = new ProxyPeoson(star);
        star.setName("Tom");
        star.setInteresters("basketball");
        star.setAge(32);
        star.setHeight(174);
        //明星姓名和興趣不會變。
        System.out.println("Star Name:" + proxyPeoson.getName());
        //經紀人會隱藏明星的年齡,比實際年齡小 5 歲
        System.out.println("Star Age:" + proxyPeoson.getAge());
        //經紀人會應藏明星的身高,比實際身高高 10 cm
        System.out.println("Star Height:" + proxyPeoson.getHeight());
        System.out.println("Star Intersters:" + proxyPeoson.getInteresters());
    }
}

代理模式

其實上面例子是 保護代理 的演示,比如明星某些隱私不能讓大眾知道,那麼經紀人就會拒絕告知。
如果上面的例子改為:明星不在時,他的一切事務全由經紀人代理,如果真的某些事情必須明星出面在找到他(例項化),這就是所謂的 虛擬代理直到真正需要一個物件時才建立它
如果上面的例子改為:明星不在,但通過網路和經紀人取得聯絡,互相通訊事務,經紀人遇到情況會通過網路轉發給明星,明星執行完後返回給經濟人,這就是所謂的 遠端代理呼叫代理的方法,會被代理利用網路轉發到遠端執行,並且結果會通過網路返回到代理,再由代理將結果轉給客戶

適用場景:

  • 遠端代理(Remote Proxy):為一個位於不同的地址空間的物件提供一個本地的代理物件。這個不同的地址空間可以是在同一臺主機中,也可是在另一臺主機中。
  • 虛擬代理(Virtual Proxy):根據需要建立開銷很大的物件。如果需要建立一個資源消耗較大的物件,先建立一個消耗相對較小的物件來表示,真實物件只在需要時才會被真正建立。
  • 保護代理(Protection Proxy):控制對原始物件的訪問。保護代理用於物件應該有不同的訪問許可權的時候。

優缺點:

優點:

  • 代理模式能夠協調呼叫者和被呼叫者,在一定程度上降低了系統的耦合度。

缺點:

  • 由於在客戶端和真實主題之間增加了代理物件,因此有些型別的代理模式可能會造成請求的處理速度變慢。
  • 實現代理模式需要額外的工作,有些代理模式的實現非常複雜。

與其它模式區別:

  • 介面卡模式 Adapter:介面卡模式為它所適配的物件提供了一個不同的介面。相反,代理提供了與它的實體相同的介面。然而,用於訪問保護的代理可能會拒絕執行實體會執行的操作,因此,它的介面實際上可能只是實體介面的一個子集。

  • 裝飾器模式 Decorator:儘管Decorator的實現部分與代理相似,但 Decorator 的目的不一樣。Decorator 為物件新增一個或多個功能,而代理則控制對物件的訪問。