以下都是本人收集和總結(jié)的內(nèi)容:
1.什么是代理模式
代理模式(Proxy Pattern)也稱作為委托模式蚕断。在生活中代理也是隨處可見欢伏,例如香港代購,代理品牌電腦出售店等亿乳。而在開發(fā)中也是被經(jīng)常被使用到的一種設計模式硝拧。代理模式的作用是:為其他對象提供一種代理以控制對這個對象的訪問。對于代理模式可以分為兩大類葛假,分別是靜態(tài)代理和動態(tài)代理障陶。下面就開始對這兩種類型的代理模式進行詳細介紹。
2. 什么是靜態(tài)代理
在這里通過一個場景來展開描述代理模式⊥┛睿現(xiàn)在我想按照自己想要的配置來組裝一臺電腦咸这。于是我將主板,內(nèi)存條魔眨,顯卡媳维,機箱酿雪,顯示器等所有的配件都買回來了≈豆簦可是這個時候遇到了一個難題指黎,我不會組裝呀。于是我?guī)е@些配件去找專業(yè)人士為我組裝電腦州丹。對于電腦的組裝內(nèi)部細節(jié)部分步驟比較多醋安。在這里作為舉例說明,將組裝電腦的過程主要分為三個步驟墓毒。這三個步驟分別是安裝主機吓揪,設置顯示器,安裝操作系統(tǒng)所计。
2.1 靜態(tài)代理簡單實現(xiàn)
接下來我們針對上述場景柠辞,來實現(xiàn)代理模式。首先來看一下它的UML類圖主胧。
從上述大概看出代理模式創(chuàng)建很簡單叭首。在這里定義了一個電腦公司的接口。在這個接口里面是一些出售電腦并且組裝的實現(xiàn)步驟踪栋。而后又定義了一個客戶類和一個銷售的代理類焙格,分別實現(xiàn)這個接口。之后出售電腦的這些事情全部都交由這個銷售代理類來實現(xiàn)夷都。下面就來看一下具體的代碼實現(xiàn)眷唉。
這里定義一個電腦公司的接口,在接口里面分別定義了對電腦的出售,主機的安裝和操作系統(tǒng)的安裝损肛。
public interface IComputerFirmbuild {
void saleComputer();
void installHost();
void installOS();
}
下面這個是客戶類厢破,實現(xiàn)了IComputerFirmbuild接口。也是對電腦服務的具體操作步驟治拿。
public class Customer implements IComputerFirmbuild{
@Override
public void saleComputer() {
System.out.println("購買電腦");
}
@Override
public void installHost() {
System.out.println("安裝主機");
}
@Override
public void installOS() {
System.out.println("安裝操作系統(tǒng)");
}
}
還有個代理類摩泪。這個代理類同樣也繼承自IComputerFirmbuild接口。在這個代理類中還持有被代理的引用劫谅,也就是Customer類见坑。通過調(diào)用被代理類Customer的方法,來實現(xiàn)代理功能捏检。
public class SalerProxy implements IComputerFirmbuild{
private IComputerFirmbuild saler;
public SalerProxy(IComputerFirmbuild saler) {
this.saler = saler;
}
@Override
public void saleComputer() {
this.Saler.saleComputer();
}
@Override
public void installHost() {
this.Saler.installHost();
}
@Override
public void installOS() {
this.saler.installOS();
}
}
下面就通過一個Client類荞驴,來看一下具體的調(diào)用執(zhí)行關系。
public class Client {
public static void main(String[] args) {
IComputerFirmbuild customer = new Customer();
IComputerFirmbuild proxy = new SalerProxy(customer);
proxy.saleComputer();
proxy.setDisplay();
proxy.installOS();
}
}
在這個Client類中贯城,可以看到熊楼,所有的事情都交由代理類處理了。然后在看一下運行結(jié)果能犯。
log --> 購買電腦
log --> 安裝主機
log --> 安裝操作系統(tǒng)
對于這個代理類中鲫骗,也能夠?qū)崿F(xiàn)不同的接口來完成不同功能的整合犬耻。在這里就不在詳細贅述。下面就來看一下代理模式的通用代碼执泰。
2.2靜態(tài)代理通用模板
在這里首先來看一下代理模式的通用類圖枕磁。
ISubject(抽象主題類):在這個類中,主要聲明真實主題類和代理類的共同方法术吝。它既可以是一個接口也可以是一個抽象類计济。
RealSubject(真實主題類):這是被代理類,具體的業(yè)務實現(xiàn)都在這個類中排苍。
Proxy(代理類):這是一個代理類沦寂,在這個代理類中它持有真實主題類的對象。通過調(diào)用真實主題類的方法來實現(xiàn)代理淘衙。
下面來看一下通用代碼:
抽象主題類
public interface ISubject {
public void request();
}
實現(xiàn)抽象主題的真實主題類
public class RealSubject implements ISubject{
@Override
public void request() {
System.out.println("我是真實對象");
}
}
代理類
public class Proxy implements ISubject{
private ISubject subject;
public Proxy(ISubject subject) {
this.subject = subject;
}
@Override
public void request() {
this.subject.request();
}
}
客戶類
public class Client {
public static void main(String[] args) {
ISubject subject = new RealSubject();
Proxy proxy = new Proxy(subject);
proxy.request();
}
}
以上就是靜態(tài)代理類的實現(xiàn)凑队。
從上面的分析出可以看出,對靜態(tài)代理模式幔翰,代理者的代碼都是通過程序員或者是通過一些自動化的工具生成的固定代碼然后再對他們進行編譯。這樣也就意味著在我們的代碼運行之前代理類的Class文件就已經(jīng)存在了西壮。
3. 什么是動態(tài)代理
3.1動態(tài)代理簡單實現(xiàn)
在這里再來看一下動態(tài)代理遗增。對于動態(tài)代理,在程序運行時款青,動態(tài)的創(chuàng)建一個代理類以及代理類的對象做修,當然也能夠創(chuàng)建一個實現(xiàn)多個接口的代理類。在動態(tài)代理類中使用了Java中的反射機制抡草,來生成了代理類的對象饰及。并且Java也為我們提供了一個動態(tài)代理接口InvocationHandler,對被代理類的方法進行代理康震。在使用動態(tài)代理類時燎含,必須實現(xiàn)InvocationHandler接口。
對于InvocationHandler接口腿短,我們必須手動實現(xiàn)的它的invoke方法屏箍,正是在InvocationHandler中的invoke方法中完成了對真實方法的調(diào)用。也就是說所有被代理的方法都是交由這個InvocationHandler進行處理橘忱。在這里首先看一下這個InvocationHandler接口赴魁。
下面就來看一下具體的代碼實現(xiàn)。對于上面的IComputerFirmbuild接口和Customer不需要改變钝诚。所以在這里只需要一個實現(xiàn)InvocationHandler接口的CustomerHandler類颖御。然后在對Client做一次修改即可。在這里看一下CustomerHandler類凝颇。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class CustomerHandler implements InvocationHandler{
private Object obj = null;
public CustomerHandler(Object object) {
this.obj = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
return method.invoke(this.obj, args);
}
}
再看一下Client類潘拱。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
IComputerFirmbuild computerFirmbuild = new Customer();
InvocationHandler handler = new CustomerHandler(computerFirmbuild);
IComputerFirmbuild proxy = (IComputerFirmbuild)Proxy.newProxyInstance(computerFirmbuild.getClass().getClassLoader(),
new Class[]{IComputerFirmbuild.class}, handler);
proxy.saleComputer();
proxy.installHost();
proxy.installOS();
}
}
這樣就通過動態(tài)代理模式實現(xiàn)了上述的情形疹鳄。對于運行結(jié)果與上面一樣,在這里就不在貼出泽铛。下面來看一下動態(tài)代理的通用模板尚辑。
通過DynamicProxy,RealSubject可以在運行時動態(tài)改變盔腔,需要控制的接口Subject也可以在運行時改變杠茬,控制的方式DynamicSubject類也可以動態(tài)改變,從而實現(xiàn)了非常靈活的動態(tài)代理關系弛随。
3.2動態(tài)代理通用模板
在這里再看一下動態(tài)代理的通用類圖瓢喉。
在這里通過DynamicProxy來創(chuàng)建一個Proxy對象。并且它依賴于InvocationHandler舀透。并且是InvocationHandler來進行實際的業(yè)務處理栓票。下面就來看一下動態(tài)代理的通用代碼。
抽象主題類
public interface ISubject {
void request();
}
真實主題類
public class RealSubject implements ISubject{
@Override
public void request() {
//業(yè)務處理
}
}
InvocationHandler的實現(xiàn)類
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler{
private Object target = null;
public MyInvocationHandler(Object object) {
this.target = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(this.target, args);
}
}
DynamicProxy類
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class DynamicProxy<T> {
@SuppressWarnings("unchecked")
public static <T> T newProxyInstance(ClassLoader classLoader, Class<?>[] interfaces,InvocationHandler handler){
return (T)Proxy.newProxyInstance(classLoader, interfaces, handler);
}
}
Client類
public class Client {
public static void main(String[] args) {
ISubject subject = new RealSubject();
InvocationHandler handler = new MyInvocationHandler(subject);
ISubject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), handler);
proxy.request();
}
}
4. 總結(jié)
從代理模式可以看出代理對象可以在客戶端和目標對象之間起到中介的作用愕够,這樣起到了中介的作用和保護了目標對象的作用走贪,并且擴展性很高。