什麼叫做代理模式?
代理模式在設計模式中的定義就是:爲其他對象提供一種代理來控制這個對象的訪問。就是在一些客戶不想或者不能直接引用一個對象,而代理對象可以在客戶和目標之間起到一箇中介作用,去掉客戶不能看到的內容和服務或者增添客戶需要的額外服務。即通過代理對象訪問目標對象。
代理模式分爲靜態代理和動態代理!(Spring AOP的底層就是代理模式)
1:靜態代理:
例如:一個人需要租房子(客戶)想要租房子,而恰好有一位房東(目標對象/真實角色)需要出租自己的房子。但是房東只是想把房子租出去,至於租給誰怎麼租合同怎麼籤這些繁瑣的事情他不想去管理,這個時候他就可以找一個房屋中介(代理角色),讓中介幫他把房子租出。然後房東跟中介都有一個共同點就是要把房子租出去(接口)。這個時候需要租房子的人就可以直接去找中介租房子。而不需要去找房東。這種方式就叫做靜態代理。
package com.lrx.demo01;
//租房接口
public interface Rent {
public void rent();
}
package com.lrx.demo01;
//真實角色(房東)
public class Host implements Rent {
public void rent() {
System.out.println("房東要出租房子!");
}
}
package com.lrx.demo01;
//代理角色(中介)
public class Proxy implements Rent {
private Host host;
public Proxy(){
};
public Proxy(Host host) {
this.host = host;
};
public void rent() {
host.rent();
seeHouse();
signContract();
rentCollection();
}
//看房
public void seeHouse(){
System.out.println("中介帶你看房子!");
}
//籤合同
public void signContract(){
System.out.println("中介和你籤合同!");
}
//收房租
public void rentCollection(){
System.out.println("中介收取你的房租");
}
}
package com.lrx.demo01;
//客戶(租客)
public class Client {
public static void main(String[] args) {
Host host=new Host();
//直接把房東host(真實角色)的房子丟給代理角色proxy,讓他去出租。
Proxy proxy=new Proxy(host);
proxy.rent();
}
}
輸出結果爲:
房東要出租房子!
中介帶你看房子!
中介和你籤合同!
中介收取你的房租
角色分析:
抽象角色:一般使用接口和抽象類來解決。
真實角色:被代理的角色
代理角色:代理真實角色,代理真實角色後,我們一般會做一些附屬操作
客戶:訪問代理對象的人
代理模式的好處:
可以使真實角色的操作更加純粹!不用去關注一些公共的業務
公共業務就交給了代理角色!實現了業務的分工
公共業務發生擴展的時候,方便集中管理
缺點:
一個真實角色就會產生一個代理角色;代碼量會翻倍,開發效率會變低(動態代理可解決)
2:動態代理:
動態代理和靜態代理角色一樣
動態代理類(代理角色類)是動態生成的,不是我們手動編寫好的類。
動態代理分爲兩大類:基於接口的動態代理和基於類的動態代理
基於接口—JDK動態代理(我們在這裏使用):
基於類:cglib
java字節碼實現:javassist
需要了解兩個類:
Proxy:代理
InvocationHandler:調用處理程序接口
package com.lrx.demo02;
//租房接口
public interface Rent {
public void rent();
}
package com.lrx.demo02;
import com.lrx.demo02.Rent;
//真實角色(房東)
public class Host implements Rent{
public void rent() {
System.out.println("房東要出租房子!");
}
}
//我們會用這個類自動生成代理類
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//生成得到代理類
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
};
//處理代理實例,並返回結果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
//動態代理的本質就是使用反射機制實現
Object result=method.invoke(rent,args);
rentCollection();
return result;
}
public void seeHouse(){
System.out.println("中介帶你看房子!");
}
public void rentCollection(){
System.out.println("收房租!");
}
}
package com.lrx.demo02;
public class Client {
public static void main(String[] args) {
//真實角色描寫
Host host=new Host();
//調用程序
ProxyInvocationHandler pih=new ProxyInvocationHandler();
//通過調用程序處理角色來處理我們要調用的接口對象
pih.setRent(host);
Rent proxy= (Rent) pih.getProxy();
proxy.rent();
}
}
輸出結果:
中介帶你看房子!
房東要出租房子!
收房租!
一個動態代理類代理的是一個接口,一般就是對應的一類業務,一個動態代理類可以代理多個類!只要是實現了同一個接口即可