Java 靜態代理

來源:互聯網
上載者:User

標籤:test   pac   end   ati   建立   fun   code   通過   request   

Java 靜態代理

靜態代理通常用於對原有商務邏輯的擴充。比如持有二方包的某個類,並調用了其中的某些方法。然後出於某種原因,比如記錄日誌、列印方法執行時間,但是又不好將這些邏輯寫入二方包的方法裡。所以可以建立一個代理類實現和二方方法相同的方法,通過讓代理類持有真實對象,然後在原代碼中調用代理類方法,來達到添加我們需要商務邏輯的目的。

這其實也就是代理模式的一種實現,通過對真實對象的封裝,來實現擴充性。

一個典型的代理模式通常有三個角色,這裡稱之為**代理三要素**

package singleton;

public class TestProxy {
public static void main(String[] args) {
Subject subject = new ProxySubject();
subject.request();
}
}

抽象角色

abstract class Subject {
public abstract void request();
}

真實角色

class RealSubject extends Subject {
@Override
public void request() {
System.out.println("From real subject");
}

}

代理角色

class ProxySubject extends Subject {
private RealSubject realSubject;// 代理角色內部引用了真是角色

@Override
public void request() {
this.preRequest();// 在真實角色操作之前所附加的操作
if (null == realSubject) {
realSubject = new RealSubject();
}
realSubject.request();// 真實角色鎖完成的事情
this.postRequest();// 在真實角色操作之後所附加的操作
}

private void preRequest() {
System.out.println("pre request");
}

private void postRequest() {
System.out.println("post request");
}

}

運行結果:

pre request
From real subject
post request

也可以用介面表示抽象角色

共同介面
public interface Action {    public void doSomething();}
真實對象
public class RealObject implements Action{    public void doSomething() {        System.out.println("do something");    }}
代理對象
public class Proxy implements Action {    private Action realObject;    public Proxy(Action realObject) {        this.realObject = realObject;    }    public void doSomething() {        System.out.println("proxy do");        realObject.doSomething();    }}

運行代碼

    Proxy proxy = new Proxy(new RealObject());    proxy.doSomething();

這種代理模式也最為簡單,就是通過proxy持有realObject的引用,並進行一層封裝。

靜態代理的優點和缺點

先看看代理模式的優點: 擴充原功能,不侵入原代碼。

再看看這種代理模式的缺點:

假如有這樣一個需求,有十個不同的RealObject,同時我們要去代理的方法是不同的,比要代理方法:doSomething、doAnotherThing、doTwoAnotherThing,添加代理前,原代碼可能是這樣的:

realObject.doSomething();realObject1.doAnotherThing();realObject2.doTwoAnother();

為瞭解決這個問題,我們有方案一:

為這些方法建立不同的代理類,代理後的代碼是這樣的:

proxy.doSomething();proxy1.doAnotherThing();proxy2.doTwoAnother();

當然,也有方案二:

通過建立一個proxy,持有不同的realObject,實現Action1、Action2、Action3介面,來讓代碼變成這樣:

proxy.doSomething();proxy.doAnotherThing();proxy.doTwoAnother();

於是你的代理模型會變成這樣:

毫無疑問,僅僅為了擴充同樣的功能,在方案一種,我們會重複建立多個邏輯相同,僅僅RealObject引用不同的Proxy。

而在方案二中,會導致proxy的膨脹,而且這種膨脹往往是無意義的。此外,假如方法簽名是相同的,更需要在調用的時候引入額外的判斷邏輯。

package Test;

public class TestProxy {
public static void main(String[] args) {
Action1 action1 = new ProxySubject();
action1.requestFirstThing();
Action2 action2 = new ProxySubject();
action2.requestSecondThing();
Action3 action3 = new ProxySubject();
action3.requestThirdThing();

}
}

interface Action1 {
void requestFirstThing();
}

interface Action2 {
void requestSecondThing();
}

interface Action3 {
void requestThirdThing();
}

class RealSubject1 implements Action1 {
@Override
public void requestFirstThing() {
System.out.println("From real subject1");
}

}

class RealSubject2 implements Action2 {

@Override
public void requestSecondThing() {
System.out.println("From real subject2");
}
}

class RealSubject3 implements Action3 {

@Override
public void requestThirdThing() {
System.out.println("From real subject3");
}
}

class ProxySubject implements Action1, Action2, Action3 {
private RealSubject1 realSubject1;// 代理角色內部引用了真是角色
private RealSubject2 realSubject2;// 代理角色內部引用了真是角色
private RealSubject3 realSubject3;// 代理角色內部引用了真是角色

@Override
public void requestFirstThing() {
this.preRequest();// 在真實角色操作之前所附加的操作
if (null == realSubject1) {
realSubject1 = new RealSubject1();
}
realSubject1.requestFirstThing();// 真實角色鎖完成的事情
this.postRequest();// 在真實角色操作之後所附加的操作
}

private void preRequest() {
System.out.println("pre request");
}

private void postRequest() {
System.out.println("post request");
}

@Override
public void requestThirdThing() {
this.preRequest();// 在真實角色操作之前所附加的操作
if (null == realSubject2) {
realSubject2 = new RealSubject2();
}
realSubject2.requestSecondThing();// 真實角色鎖完成的事情
this.postRequest();// 在真實角色操作之後所附加的操作

}

@Override
public void requestSecondThing() {
this.preRequest();// 在真實角色操作之前所附加的操作
if (null == realSubject3) {
realSubject3 = new RealSubject3();
}
realSubject3.requestThirdThing();// 真實角色鎖完成的事情
this.postRequest();// 在真實角色操作之後所附加的操作
}
}

運行結果:

pre request
From real subject1
post request
pre request
From real subject3
post request
pre request
From real subject2
post request

Java 靜態代理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.