設計模式之代理模式(proxy pattern)

代理模式的本質是一箇中間件,主要目的是解耦合服務提供者和使用者。使用者經過代理間接的訪問服務提供者,便於後者的封裝和控制。是一種結構性模式。html

1.目的

爲外部調用者提供一個訪問服務提供者的代理對象。緩存

2.動機

限制對目標對象的直接訪問,下降耦合度。服務器

3.優缺點

優勢: 網絡

  • 低耦合
  • 易擴展
  • 靈活度高

缺點:異步

  • 間接訪問可能會延遲請求相應
  • 增長工做量

4.分類

  • 靜態代理
  • 動態代理

  代理類自己的實現可能並不簡單,加上每個須要代理的對象均均須要實現一個代理類,其工做量自己比較大,易出錯。ide

  所謂動態代理(DynamicProxy)是指在程序運行時動態的生成對目標對象的訪問接口。網站

  本文主要介紹前者,關於後者能夠參考JDK自帶的動態代理。this

5.主要用途

代理模式在如下場景比較適用:google

     一、遠程代理。 二、虛代理。 三、保護代理。四、智能指引代理。五、寫時複製(Copy-on-Write)代理。  六、緩存代理。 七、防火牆代理。 八、同步化代理。url

6.原理

下面是GoF介紹典型的代理模式UML類圖

Subject:

 定義RealSubject對外的接口,且這些接口必須被Proxy實現,這樣外部調用proxy的接口最終都被轉化爲對realsubject的調用。

RealSubject:

 真正的目標對象。

Proxy:

 目標對象的代理,負責控制和管理目標對象,並間接地傳遞外部對目標對象的訪問。

  1. Remote Proxy: 對本地的請求以及參數進行序列化,向遠程對象發送請求,並對響應結果進行反序列化,將最終結果反饋給調用者;
  2. Virtual Proxy: 當目標對象的建立開銷比較大的時候,可使用延遲或者異步的方式建立目標對象;
  3. Protection Proxy: 細化對目標對象訪問權限的控制;

7.實現

 下面咱們使用兩個例子來實際體驗一下代理模式的應用

網絡代理

對於一些國內不能直接訪問的網站,合法的使用的網絡代理能夠實現對目標網站的訪問;

定義公共接口類Server:

public interface Server{
    void visit(String url);
}

  代理服務器ProxyServer:

public class ProxyServer implements Server{
 
   private RealServer realServer;
 
   public ProxyServer(String serverName){
      this.realServer = new RealServer(serverName);
   }
 
   @Override
   public void visit(String url) {
      realServer.visit(url);
   }
}

  目標服務器RealServer:

public class RealServer implements Server {
    private String serverName;
    public RealServer(String serverName) {
        this.serverName = serverName;
        System.out.println("This is " + serverName);
    }
    
    @Override
    public void visit(String url) {
        response(url);
    }
    
    private void response(String res) {
        System.out.println("This is response of " + res + " from server:" + serverName);
    }
}

 演示:

public class Demo {
    public static void main(String[] args) {
        Server server = new ProxyServer("www.google.com");
        server.visit("map.google.com");
    }
}

智能指針引用計數

下面使用代理模式簡單的模擬指針引用計數問題

接口類Obj:

public interface Obj{
    void GetAttr();
    Obj copy();
    void delete();
}

  智能指針類SmartPointer:

public class SmartPointer implements Obj{
 
   private RealObj realObj;
   private int counter = 1;
 
   public SmartPointer(String objType){
      this.realObj = new RealObj(objType);
   }
   
   @Override
   public void GetAttr() {
       if(counter > 0) {
           realObj.GetAttr();
       }
       System.out.println("Smart Ref: " + counter);
   }
       
    public Obj copy() {
        if(counter > 0) {
            counter += 1;
            return this;
        }
        System.out.println("Invalid Pointer!");
        return null;
    }
    
    public void delete() {
        if(counter > 0) {
            counter -= 1;
            if(0 == counter) {
                realObj = null;
            }
        }
        else {
            System.out.println("Invalid Pointer!");
        }
    }
}
View Code

 被引用對象類RealObj:

public class RealObj implements Obj {
    private String objType;
    public RealObj(String objType) {
        this.objType = objType;
        System.out.println("Create Obj: " + objType);
    }
    
    @Override
    public void GetAttr() {
        System.out.println("get attr of real obj " + objType);
    }

    @Override
    public Obj copy() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void delete() {
        // TODO Auto-generated method stub
        
    }
}
View Code

 參考:

GoF《Design Patterns: Elements of Reusable Object-Oriented Software》

https://www.runoob.com/design-pattern/proxy-pattern.html

相關文章
相關標籤/搜索