Proxy Pattern
我只想說簡書這個代碼高亮比CSDN好了不要太多,以后都雙平臺發(fā)布文章啦,喜歡的朋友可以關(guān)注我一下。
概述
Proxy代理模式,是GOF中一種常用的設(shè)計模式。
代理模式就是給一個對象提供一個代理,并由代理對象控制對原對象的引用。它使得客戶不能直接與真正的目標對象通信。代理對象是目標對象的代表,其他需要與這個目標對象打交道的操作都是和這個代理對象在交涉。
代理對象可以在客戶端和目標對象之間起到中介的作用,這樣起到了的作用和保護了目標對象的,同時也在一定程度上面減少了系統(tǒng)的耦合度。
參與者:
Subject
: 抽象角色。聲明真實對象和代理對象的共同接口。
Proxy
: 代理角色。代理對象與真實對象實現(xiàn)相同的接口,所以它能夠在任何時刻都能夠代理真實對象。代理角色內(nèi)部包含有對真實對象的引用,所以她可以操作真實對象,同時也可以附加其他的操作,相當于對真實對象進行封裝。
RealSubject
: 真實角色。它代表著真實對象,是我們最終要引用的對象。
代碼示例
Github 源碼: https://github.com/onlynight/Proxy
1.首先定義一個抽象能力接口
定義被代理對象能夠想外部提供的能力。
public interface Subject {
/**
* 封裝代理操作
*/
void operation();
}
2.被代理對象實現(xiàn)接口
被代理對象實現(xiàn)抽象能力接口,并實現(xiàn)其內(nèi)部功能。接口函數(shù)內(nèi)部實現(xiàn)就代表了被代理對象對外的提供的能力。
public class RealSubject implements Subject {
@Override
public void operation() {
// 調(diào)用內(nèi)部函數(shù),實現(xiàn)改函數(shù)的真正功能
operation1();
System.out.println("real operation");
}
private void operation1() {
//todo real operation1
}
}
3.代理實現(xiàn)接口
/**
* Created by lion on 2016/10/11.
* 這類的構(gòu)造函數(shù)需要從外部傳入被代理對象,這種不太符合真實的使用場景
*/
public class Proxy implements Subject {
private Subject subject;
public Proxy(Subject subject) {
this.subject = subject;
}
@Override
public void operation() {
System.out.println("before operation");
subject.operation();
System.out.println("end operation");
}
}
一般采用代理就是不想讓真正的對象直接和外部接觸,通過代理代碼解耦和。
/**
* Created by lion on 2016/10/14.
* 通過靜態(tài)方法獲取代理,這里可以設(shè)計成單例,也可以從遠程服務(wù)中獲取被代理對象。
*/
public class Proxy implements Subject {
private Proxy() {
}
public static Proxy getDefault() {
// 這里又很多想象空間,具體怎么使用就留給大家啦。
return new Proxy();
}
/**
* 這里演示內(nèi)部構(gòu)造方式,控制外部訪問權(quán)限。
* 只要不把對象本身能直接外部訪問即可。
*/
private Subject subject = new RealSubject();
@Override
public void operation() {
System.out.println("Proxy start");
subject.operation();
System.out.println("Proxy end");
}
}
測試代碼如下
public class Main {
public static void main(String[] args) {
System.out.println("demo1>");
demo1();
System.out.println("\ndemo2>");
demo2();
}
private static void demo1() {
Subject subject = new RealSubject();
Proxy proxy = new Proxy(subject);
proxy.operation();
}
private static void demo2() {
com.github.onlynight.proxy.privacy.Proxy.getDefault().operation();
}
}
輸出結(jié)果
demo1>
before operation
real operation
end operation
demo2>
Proxy start
real operation
Proxy end
使用場景
在需要用比較通用和復(fù)雜的對象指針代替簡單的指針的時候,使用 Proxy模式。下面是一些可以使用Proxy模式常見情況:
1.遠程代理(Remote Proxy)
遠程代理為一個位于不同的地址空間的對象提供一個本地的代理對象。這個不同的地址空間可以是在同一臺主機中,也可是在另一臺主機中,遠程代理又叫做大使(Ambassador)。
這中代理模式比較常用,后續(xù)的Android的Binder通信中使用了遠程代理模式,在其中有很好的應(yīng)用,感興趣的朋友可以查看我后續(xù)的代碼分析。Github AIDL
2.虛擬代理(Virtual Proxy)
虛擬代理根據(jù)需要創(chuàng)建開銷很大的對象。如果需要創(chuàng)建一個資源消耗較大的對象,先創(chuàng)建一個消耗相對較小的對象來表示,真實對象只在需要時才會被真正創(chuàng)建。
3.保護代理(Protection Proxy)
保護代理控制對原始對象的訪問。保護代理用于對象應(yīng)該有不同的訪問權(quán)限的時候。
4.智能指引(Smart Reference)
智能指引取代了簡單的指針,它在訪問對象時執(zhí)行一些附加操作。
5.Copy-on-Write代理
Copy-on-Write代理它是虛擬代理的一種,把復(fù)制(克?。┎僮餮舆t到只有在客戶端真正需要時才執(zhí)行。一般來說,對象的深克隆是一個開銷較大的操作,Copy-on-Write代理可以讓這個操作延遲,只有對象被用到的時候才被克隆。
由于筆者閱歷有限暫時不能提供相應(yīng)的栗子,后續(xù)的開發(fā)中如果遇到合適的栗子會持續(xù)更新,謝謝大家的支持。