`

設計模式之Proxy(代理)

阅读更多

理解並使用設計模式 , 能夠培養我們良好的面向物件編程習慣 , 同時在實際應用中 , 可以如魚得水 , 享受遊刃有餘的樂趣。

Proxy 是比較有用途的一種模式 , 而且變種較多 , 應用場合覆蓋從小結構到整個系統的大結構 ,Proxy 是代理的意思 , 我們也許有代理伺服器等概念 , 代理概念可以解釋爲 : 在出發點到目的地之間有一道中間層 , 意爲代理。

設計模式中定義 : 爲其他物件提供一種代理以控制對這個物件的訪問。

爲什麽要使用 Proxy?
1.
授權機制 不同級別的用戶對同一物件擁有不同的訪問權利 , Jive 論壇系統中 , 就使用 Proxy 進行授權機制控制 , 訪問論壇有兩種人 : 註冊用戶和遊客 ( 未註冊用戶 ),Jive 中就通過類似 ForumProxy 這樣的代理來控制這兩種用戶對論壇的訪問許可權。

2. 某個用戶端不能直接操作到某個物件 , 但又必須和那個物件有所互動。
舉例兩個具體情況
:
(1)
如果那個物件是一個是很大的圖片 , 需要花費很長時間才能顯示出來 , 那麽當這個圖片包含在文檔中時 , 使用編輯器或瀏覽器打開這個文檔 , 打開文檔必須很迅速 , 不能等待大圖片處理完成 , 這時需要做個圖片 Proxy 來代替真正的圖片。

(2)
如果那個物件在 Internet 的某個遠端伺服器上 , 直接操作這個物件因爲網路速度原因可能比較慢 , 那我們可以先用 Proxy 來代替那個物件。

總之原則是 , 對於開銷很大的物件 , 只有在使用它時才創建 , 這個原則可以爲我們節省很多寶貴的 Java 記憶體。 所以 , 有些人認爲 Java 耗費資源記憶體 , 我以爲這和程式編制思路也有一定的關係。

如何使用 Proxy?
Jive論壇系統 爲例 , 訪問論壇系統的用戶有多種類型 : 註冊普通用戶 論壇管理者 系統管理者 遊客 , 註冊普通用戶才能發言 ; 論壇管理者可以管理他被授權的論壇 ; 系統管理者可以管理所有事務等 , 這些許可權劃分和管理是使用 Proxy 完成的。

Forum Jive 的核心介面 , Forum 中陳列了有關論壇操作的主要行爲 , 如論壇名稱 論壇描述的獲取和修改 , 帖子發表刪除編輯等。

ForumPermissions 中定義了各種級別許可權的用戶 :

public class ForumPermissions implements Cacheable {

/**
* Permission to read object.
*/
public static final int READ = 0;

/**
* Permission to administer the entire sytem.
*/
public static final int SYSTEM_ADMIN = 1;

/**
* Permission to administer a particular forum.
*/
public static final int FORUM_ADMIN = 2;

/**
* Permission to administer a particular user.
*/
public static final int USER_ADMIN = 3;

/**
* Permission to administer a particular group.
*/
public static final int GROUP_ADMIN = 4;

/**
* Permission to moderate threads.
*/
public static final int MODERATE_THREADS = 5;

/**
* Permission to create a new thread.
*/
public static final int CREATE_THREAD = 6;

/**
* Permission to create a new message.
*/
public static final int CREATE_MESSAGE = 7;

/**
* Permission to moderate messages.
*/
public static final int MODERATE_MESSAGES = 8;

.....

public boolean isSystemOrForumAdmin() {
   return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]);
}

.....

}

因此 ,Forum 中各種操作許可權是和 ForumPermissions 定義的用戶級別有關係的 , 作爲介面 Forum 的實現 :ForumProxy 正是將這種對應關係聯繫起來。比如 , 修改 Forum 的名稱 , 只有論壇管理者或系統管理者可以修改 , 代碼如下 :

public class ForumProxy implements Forum {

private ForumPermissions permissions;
private Forum forum;
this.authorization = authorization;

public ForumProxy(Forum forum, Authorization authorization,
ForumPermissions permissions)
{
this.forum = forum;
this.authorization = authorization;
this.permissions = permissions;
}

.....

public void setName(String name) throws UnauthorizedException,
ForumAlreadyExistsException
{
   // 只有是系統或論壇管理者才可以修改名稱
  
if (permissions.isSystemOrForumAdmin()) {
    
forum.setName(name);
  
}
  
else {
    
throw new UnauthorizedException();
   }
}

...

}

DbForum 才是介面 Forum 的真正實現 , 以修改論壇名稱爲例 :

public class DbForum implements Forum, Cacheable {
...

public void setName(String name) throws ForumAlreadyExistsException {

  
....

  
this.name = name;
   // 這裏真正將新名稱保存到資料庫中
   saveToDb();

   ....
}


...

}

凡是涉及到對論壇名稱修改這一事件 , 其他程式都首先得和 ForumProxy 打交道 , ForumProxy 決定是否有許可權做某一樣事情 ,ForumProxy 是個名副其實的 " 閘道 "," 安全代理系統 "

在平時應用中 , 無可避免總要涉及到系統的授權或安全體系 , 不管你有無意識的使用 Proxy, 實際你已經在使用 Proxy 了。

我們繼續結合 Jive 談入深一點 , 下面要涉及到工廠模式了 , 如果你不瞭解工廠模式 , 請看我的另外一篇文章 :設計模式之 Factory

我們已經知道 , 使用 Forum 需要通過 ForumProxy,Jive 中創建一個 Forum 是使用 Factory 模式 , 有一個總的抽象類別 ForumFactory, 在這個抽象類別中 , 呼叫 ForumFactory 是通過 getInstance() 方法實現 , 這裏使用了 Singleton( 也是設計模式之一 , 由於介紹文章很多 , 我就不寫了 ,看這裏 ),getInstance() 返回的是 ForumFactoryProxy

爲什麽不返回 ForumFactory, 而返回 ForumFactory 的實現 ForumFactoryProxy?
原因是明顯的 , 需要通過代理確定是否有許可權創建 forum

ForumFactoryProxy 中我們看到代碼如下 :

public class ForumFactoryProxy extends ForumFactory {

   protected ForumFactory factory;
  
protected Authorization authorization;
   protected ForumPermissions permissions;

   public ForumFactoryProxy(Authorization authorization, ForumFactory factory,
  
ForumPermissions permissions)
  
{
    
this.factory = factory;
    
this.authorization = authorization;
    
this.permissions = permissions;
   }

   public Forum createForum(String name, String description)
      
throws UnauthorizedException, ForumAlreadyExistsException
  
{
     // 只有系統管理者才可以創建
forum
    
if (permissions.get(ForumPermissions.SYSTEM_ADMIN)) {
      
Forum newForum = factory.createForum(name, description);
      
return new ForumProxy(newForum, authorization, permissions);
    
}
    
else {
      
throw new UnauthorizedException();
   }
}

方法 createForum 返回的也是 ForumProxy, Proxy 就象一道牆 , 其他程式只能和 Proxy 交互操作。

注意到這裏有兩個 Proxy:ForumProxy ForumFactoryProxy 代表兩個不同的職責 : 使用 Forum 和創建 Forum;
至於爲什麽將使用物件和創建物件分開 , 這也是爲什麽使用 Factory 模式的原因所在 : 是爲了 " 封裝 " " 分派 "; 換句話說 , 盡可能功能單一化 , 方便維護修改。

Jive 論壇系統中其他如帖子的創建和使用 , 都是按照 Forum 這個思路而來的。

以上我們討論了如何使用 Proxy 進行授權機制的訪問 ,Proxy 還可以對用戶隱藏另外一種稱爲 copy-on-write 的優化方式。拷貝一個龐大而複雜的物件是一個開銷很大的操作 , 如果拷貝過程中 , 沒有對原來的物件有所修改 , 那麽這樣的拷貝開銷就沒有必要。用代理延遲這一拷貝過程。

比如 : 我們有一個很大的 Collection, 具體如 hashtable, 有很多用戶端會並發同時訪問它。其中一個特別的用戶端要進行連續的資料獲取 , 此時要求其他用戶端不能再向 hashtable 中增加或刪除 東東。

最直接的解決方案是 : 使用 collection lock, 讓這特別的用戶端獲得這個 lock, 進行連續的資料獲取 , 然後再釋放 lock
public void foFetches(Hashtable ht){
  
synchronized(ht){
     // 具體的連續資料獲取動作。。
   }

}

但是這一辦法可能鎖住 Collection 會很長時間 , 這段時間 , 其他用戶端就不能訪問該 Collection 了。

第二個解決方案是 clone 這個 Collection, 然後讓連續的資料獲取針對 clone 出來的那個 Collection 操作。這個方案前提是 , 這個 Collection 是可 clone , 而且必須有提供深度 clone 的方法。 Hashtable 就提供了對自己的 clone 方法 , 但不是 Key value 物件的 clone, 關於 Clone 含義可以參考 專門文章
public void foFetches(Hashtable ht){

   Hashttable newht=(Hashtable)ht.clone();

}

問題又來了 , 由於是針對 clone 出來的物件操作 , 如果原來的母體被其他用戶端操作修改了 , 那麽對 clone 出來的物件操作就沒有意義了。

最後解決方案 : 我們可以等其他用戶端修改完成後再進行 clone, 也就是說 , 這個特別的用戶端先通過呼叫一個叫 clone 的方法來進行一系列資料獲取操作。但實際上沒有真正的進行物件拷貝 , 直至有其他用戶端修改了這個物件 Collection

使用 Proxy 實現這個方案。這就是 copy-on-write 操作。

Proxy 應用範圍很廣 , 現在流行的分佈計算方式 RMI Corba 等都是 Proxy 模式的應用。

分享到:
评论

相关推荐

    设计模式之代理模式proxy

    **设计模式之代理模式(Proxy Pattern)** 设计模式是软件工程中的一种最佳实践,它是在特定情境下解决常见问题的模板。代理模式是其中一种行为设计模式,它的核心思想是为一个对象提供一个替身或者代理,以控制对...

    设计模式C++学习之代理模式(Proxy)

    代理模式是一种设计模式,它是结构型模式之一,主要用于在客户端和目标对象之间建立一个代理对象,以便控制对目标对象的访问。在C++中,代理模式可以用来为其他对象提供一种代理以控制对这个对象的访问,或者增加...

    设计模式之代理模式proxy.zip

    代理模式是一种常用的设计模式,它在软件开发中扮演着重要的角色。代理模式允许我们为一个对象创建一个代理,这个代理对象在客户端和目标对象之间起到中介的作用,可以增强或控制对目标对象的访问。代理模式的主要...

    c++-设计模式之代理模式(Proxy)

    代理模式(Proxy Pattern)是一种结构型设计模式,用于为其他对象提供一种代理以控制对这个对象的访问。代理模式通常用于保护、延迟加载、记录请求等场景,可以在不改变原有对象的情况下为其增加新的功能。 代理...

    设计模式之代理模式Proxy

    代理模式是设计模式中的一种结构型模式,它在对象交互中起到了中介的作用,允许通过代理对象来控制对原对象的访问。代理模式的核心思想是为一个对象提供一个替身,以便增加新的功能或者控制对原对象的访问。这种模式...

    java 设计模式之代理模式(Proxy Pattern)实现代码及设计详解:动态代理模式、静态代理模式

    在这些模式中,代理模式(Proxy Pattern)是一种常用的结构型设计模式,它允许我们为一个对象创建一个代理,该代理对象在客户端和目标对象之间起到中介的作用,可以增加额外的功能或控制访问。 代理模式分为两种...

    Android设计模式之代理模式(Proxy Pattern)

    代理模式是设计模式的一种,它的主要目的是在不改变原有对象的基础上,为一个对象提供额外的功能或者控制对这个对象的访问。在Android开发中,代理模式的应用尤为常见,尤其在处理复杂的业务逻辑、网络请求、界面...

    设计模式 之 “代理模式[Proxy Pattern]”

    **代理模式(Proxy Pattern)**是软件设计模式中的结构型模式之一,它在对象访问控制、增加额外功能或在客户端与目标对象之间提供一个中介等方面有广泛的应用。在代理模式中,代理类作为真实对象的代表,它持有真实...

    详解设计模式中的proxy代理模式及在Java程序中的实现

    综上所述,Proxy代理模式是设计模式中的一个重要组成部分,它允许我们在不改变原始对象的情况下,通过代理对象实现对原始对象的控制和扩展。在Java中,通过Java的Proxy类和InvocationHandler接口,我们可以轻松地...

    JAVA设计模式chm文档

    设计模式之Proxy(代理) 设计模式之Adapter(适配器) 设计模式之Composite(组合) 设计模式之Decorator(油漆工) 设计模式之Bridge 设计模式之Flyweight(享元) 行为模式: 设计模式之Template 设计模式之Memento(备忘机制...

    结构型模式之代理模式(Proxy)

    代理模式是一种设计模式,属于结构型模式之一,其主要目的是为其他对象提供一个代理,以控制对该对象的访问。在实际应用中,代理模式能够帮助我们实现如下的功能: 1. 远程代理:代理对象可以代表一个位于远程系统...

    C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式)

    - **《设计模式:可复用面向对象软件的基础》GoF**:这本书是设计模式领域的经典之作,详细介绍了包括代理模式在内的多种设计模式。 - **《面向对象分析与设计》Grady Booch**:该书深入讲解了面向对象的设计原则和...

    Java设计模式——代理设计模式(静态代理和动态代理)

    代理设计模式分为静态代理和动态代理两种类型。 ### 静态代理 静态代理是在编译时就已经确定了代理关系,代理类和真实类的关系是硬编码在代理类中的。下面我们将详细介绍静态代理的实现方式: 1. **定义接口**:...

    设计模式专题,代理模式,工厂模式

    代理模式和工厂模式是两种非常重要的设计模式,它们在Java编程中有着广泛的应用。 **代理模式(Proxy Pattern)** 代理模式的核心思想是在原始对象和客户端之间插入一个代理对象,这个代理对象在客户端和原始对象...

    设计模式文档 chm

    设计模式之Proxy(代理) 设计模式之Adapter(适配器) 设计模式之Composite(组合) 设计模式之Decorator(油漆工) 设计模式之Bridge 设计模式之Flyweight(享元) 行为模式: 设计模式之Template 设计模式之Memento(备忘机制...

    C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式) (Level 300)

    本文将深入探讨C#中的一个关键设计模式——代理模式,它属于结构型模式的一种,适用于管理和控制对象的访问。我们将从概念、分类、实现方式以及实际应用等方面进行详细的讲解。 1. **代理模式概念**: 代理模式是一...

    jdbc proxy 代理类

    - 代理:代理模式是一种设计模式,它创建一个代理对象,该对象作为真实对象的替代品,可以控制对真实对象的访问或为其增加附加功能。 【压缩包子文件的文件名称列表】:net 这个文件名可能指的是网络相关的代码或...

    Proxy代理模式经典实例(绝对OOP)

    Proxy代理模式是面向对象设计模式中的重要组成部分,它在软件工程中扮演着关键角色,尤其在Java编程中。代理模式的主要目的是为一个对象提供一个替身或者占位符,以便控制对这个对象的访问。这种设计模式允许我们...

    设计模式之_代理模式

    **代理模式**是一种常用的设计模式,它在软件开发中扮演着重要的角色,特别是在对象的访问控制、性能优化、安全策略等方面。代理模式的核心思想是为一个对象提供一个替身,这个替身即代理对象,代理对象可以控制对原...

    设计模式之代理模式demo

    代理模式是一种常用的设计模式,它在软件开发中起到了中介或者代表的作用。代理模式的主要目的是为其他对象提供一种代理以控制对这个对象的访问。通过引入代理,我们可以增加新的功能,如缓存、日志记录、访问控制等...

Global site tag (gtag.js) - Google Analytics