什么是代理模式?
類似于中介抠艾,我們面對的對象變成了中介,而不是用戶個體桨昙,例如租房子:
image-20220531153138579.png
1检号、靜態(tài)代理
角色分析:
- 抽象角色:真實的目的性,一般是接口或者抽象類來解決
- 真實角色:被代理的角色
- 代理角色:代理真實角色蛙酪,代理真實角色后齐苛,一般進行一些附屬操作
- 客戶:訪問代理對象的人,辦理真實業(yè)務的人
步驟:
1.接口
public interface Rent {
//租房
void rent();
}
2.真實角色
public class Landlord implements Rent{
public void rent() {
System.out.println("房東出租了房子~");
}
}
3.代理角色
public class Proxy implements Rent {
private Landlord landlord;
public Proxy() {
}
public Proxy(Landlord landlord) {
this.landlord = landlord;
}
//額外的操作
public void seeHouse(){
System.out.println("中介帶看房~");
}
public void hetong(){
System.out.println("中介簽合同~");
}
public void fare(){
System.out.println("中介收租~");
}
public void rent() {
seeHouse();
hetong();
//真實的租房業(yè)務
landlord.rent();
fare();
}
}
4.訪問
public class Client {
public static void main(String[] args) {
//房東
Landlord landlord = new Landlord();
//中介代理房東
Proxy proxy = new Proxy(landlord);
//租房業(yè)務
proxy.rent();
}
}
5滤否、結果
/**
中介帶看房~
中介簽合同~
房東出租了房子~
中介收租~
/
真實的租房業(yè)務還是房東脸狸,但是在中介代理后會進行了一些附加的操作最仑。
優(yōu)點:
- 真實的業(yè)務對象更加關注自己的業(yè)務藐俺,不用在意一些公共的業(yè)務
- 公共交給代理炊甲,實現(xiàn)了業(yè)務分工
- 在不修改目標對象的功能前提下, 能通過代理對象對目標功能擴展
缺點:
- 每一個實際的對象都對應一個代理對象,復雜度增加
- 一旦公共接口增加方法,目標對象與代理對象都要維護
2欲芹、動態(tài)代理
- 動態(tài)代理角色和靜態(tài)代理是一樣的
- 動態(tài)代理的代理類是動態(tài)生成的卿啡,不是直接寫好的
- 動態(tài)代理分兩大類:基于接口的動態(tài)代理,基于類的動態(tài)代理
- 基于接口: JDK動態(tài)代理
- 基于類:cglib
- java字節(jié)碼實現(xiàn):javassist
需要理解兩個類:Porxy 和 InvocationHandler
Porxy:提供了創(chuàng)建動態(tài)代理類和實例的靜態(tài)方法菱父,它也是由這些方法創(chuàng)建的所有動態(tài)代理類的超類颈娜,專門用來創(chuàng)建代理對象。
InvocationHandler:是調用代理實例的程序實現(xiàn)的接口浙宜,動態(tài)實現(xiàn)官辽,每個代理實例都有一個關聯(lián)的調用處理程序。 當在代理實例上調用方法時粟瞬,方法調用將被編碼并分派到其調用處理程序的invoke方法同仆。
還是以租房子為例:
1.接口
public interface Rent {
void rent();
}
2.真實對象
public class Landlord implements Rent {
public void rent() {
System.out.println("房東出租了房子~");
}
}
3.真實對象處理類
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口 這里可以通配
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//動態(tài)的獲取代理類 固定寫法
public Object getPorxy(){
/**
* 參數(shù)
*loader - 類加載器來定義代理類
* interfaces - 代理類實現(xiàn)的接口列表
* h - 調度方法調用的調用處理函數(shù)
*/
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//處理被代理的實例 返回結果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
hetong();
//真實的租房業(yè)務
// this.log(method.getName());
//處理真實的代理對象業(yè)務
Object result = method.invoke(target,args);
fare();
return result;
}
//額外的操作
// public void log(String msg){
// System.out.println("操作了"+msg+"方法");
// }
public void seeHouse(){
System.out.println("中介帶看房~");
}
public void hetong(){
System.out.println("中介簽合同~");
}
public void fare(){
System.out.println("中介收租~");
}
}
4.測試
public static void main(String[] args) {
//真實對象
Landlord landlord = new Landlord();
ProxyInvocationHandler handler = new ProxyInvocationHandler();
//告訴處理器要代理的真實對象
handler.setTarget(landlord);
//獲取代理角色 動態(tài)生成的
Rent porxy = (Rent) handler.getPorxy();
//調用真實的業(yè)務
porxy.rent();
}
結論:
這里的代理對象是通過處理類動態(tài)的獲取的,而且通過通配改造之后裙品,該處理類可以代理一類的需要代理的對象俗批,只要是實現(xiàn)了同一個接口的對象都可以動態(tài)的獲取到代理對象铸题。
優(yōu)點:
- 基于靜態(tài)代理的基礎上赋元,一個動態(tài)代理類代理的是一個接口媳友,一般就是對應的一類業(yè)務
- 一個動態(tài)代理類可以代理多個類褒脯,只要是實現(xiàn)了同一個接口的