代理模式:
爲一個對象提供一種代理,以控制對這個對象的訪問。分爲靜態代理和動態代理。
什麼時候要用?
(1)當我們想要隱藏某個類時,可以爲其提供代理類
(2)當一個類需要對不同的調用者提供不同的調用權限時,可以使用代理類來實現
(3)當我們要擴展某個類的某個功能時,可以使用代理模式,在代理類中進行簡單擴展
(4)spring的aop就是使用了動態代理。
優點
(1)將代理對象與真實被調用的目標對象分離,降低了系統的耦合度
(2)保護目標對象
(3)增強目標對象
缺點
(1)會造成系統設計中類的數目增加
(2)在客戶端和目標對象之間增加了代理對象,會造成請求的處理速度變慢
(3)增加系統的複雜度
原理
使用一個代理將對象包裝起來,然後用該代理對象取代原始對象,任何對原始對象的調用都要通過代理。代理對象決定是否以及何時將方法調用轉到原始對象上。
分類
靜態代理
特點
靜態代理的代理類和目標對象類都是在編譯期確定下來的,所以不利於程序的擴展。而且,每一個代理類只能爲一個接口服務,這樣一來程序開發中必然產生過多的代理。
代碼實現
過程大致是這樣的:
(1)被代理類(actor)出現。
(2)代理類(agent)出現,並與被代理類產生關係。(通過實現同一個接口產生聯繫)
(3)代理類執行方法。(判斷是否接受代言的方法)
package com.revision.DesignMethod.proxyPattern;
interface Work{
void decide();
}
class Actor implements Work{
@Override
public void decide() {
System.out.println("我要聽從代理人的意見!請和我的代理人交流!");
}
}
class Agent implements Work{
Actor a = null;
public Agent(Actor a){
this.a = a;
}
@Override
public void decide() {
System.out.println("你好,我是代理!");
a.decide();
}
}
public class StaticProxyPattern {
public static void main(String[] args) {
//先new一個被代理對象
Actor actor = new Actor();
//代理類出現,並於被代理人產生關係
Agent agent = new Agent(actor);
//代理人替被代理人執行方法
agent.decide();
}
}
動態代理
特點
動態代理是在程序運行時根據需要動態創建目標類的代理對象,客戶可通過代理類來調用其它對象的方法。動態代理加入了反射,肯定會比靜態代理先進一點。
代碼實現
執行思路和靜態代理是一樣的:
(1)被代理類出現。
(2)代理類出現,並與被代理類建立關聯。
(3)代理類執行方法。(main函數中調用代理類的方法,代理類處調用被代理類的方法)
package com.revision.DesignMethod.proxyPattern;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//動態代理的使用
interface Subject{
void action();
}
//被代理類
class RealSubject implements Subject{
@Override
public void action() {
System.out.println("被代理類!");
}
}
//代理類
class MyInvocationHandler implements InvocationHandler {
Object obj;
//給被代理對象進行實例化,返回一個代理類的對象
public Object blind(Object obj){
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method,Object[] args)throws Throwable {
Object returnVal = method.invoke(obj,args);
return returnVal;
}
}
public class DynamicProxyPattern {
public static void main(String[] args) {
RealSubject real = new RealSubject();
MyInvocationHandler handler = new MyInvocationHandler();
Object obj = handler.blind(real);
Subject sub = (Subject)obj;
sub.action();
}
}