代理模式
在某些情況下,一個客戶不想或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。
代理模式的作用是:爲其他對象提供一種代理以控制對這個對象的訪問。
1).遠程代理(RemoteProxy)爲一個對象在不同的地址空間提供局部代表。
2).虛代理(VirtualProxy)根據需要創建開銷很大的對象。
3).保護代理(ProtectionProxy)控制對原始對象的訪問。
4).智能指引(SmartReference)取代了簡單的指針,它在訪問對象時執行一些附加操作。
5).當第一次引用一個持久對象時,將它裝入內存。
6).在訪問一個實際對象前,檢查是否已經鎖定了它,以確保其他對象不能改變它
靜態代理
下面我們以一個靜態代理簡要認識下代理模式
真實角色:電腦廠家
public class Computer {
public void porduce(){
System.out.println("生產電腦");
}
public void sell(){
System.out.println("銷售");
}
}
代理角色:商場
public class Market {
Computer computer = null;
public Market(){
this.computer = new Computer();
}
public void sell(){
this.computer.sell();
}
}
客戶端:
public class Client {
public static void main(String[] args) {
Market market = new Market();
market.sell();
}
}
此例子說明電腦銷售把賣電腦這件事交給商場代理銷售,這樣的代理有個缺點就是一個真實對象一個代理類,會導致類臃腫。
代理模式角色
抽象角色:聲明真實對象和代理對象的共同接口
代理角色:代理對象角色內部含有對真實對象的引用,從而可以操作真實對象,同時代理對象提供與真實對象相同的接口以便在任何時刻都能代替真實對象。同時,代理對象可以在執行真實對象操作時,附加其他的操作,相當於對真實對象進行封裝
真實角色:代理角色所代表的真實對象,是我們最終要引用的對象
客戶端:調用代理,產生行爲
下面我們參考這個例子:
抽象角色:
public interface IProduce {
public void sell();
}
真實角色:
public class Shoe implements IProduce {
@Override
public void sell() {
System.out.println("銷售鞋子");
}
}
真實角色:
public class Shoe implements IProduce {
@Override
public void sell() {
System.out.println("銷售鞋子");
}
}
代理角色:
public class ShoppingMall implements IProduce {
IProduce iProduce;
public ShoppingMall(IProduce produce){
this.iProduce = produce;
}
@Override
public void sell() {
this.iProduce.sell();
}
}
客戶端:
public class Client {
public static void main(String[] args) {
ShoppingMall shoppingMall = new ShoppingMall(new Car());
shoppingMall.sell();
shoppingMall = new ShoppingMall(new Shoe());
shoppingMall.sell();
//print
//銷售
//銷售汽車
//銷售鞋子
}
}
動態代理
public interface IConsumer {
public void buy();
public void feed();
}
真實角色:public class Teacher implements IConsumer {
@Override
public void buy() {
System.out.println("需要買一份教案!");
}
@Override
public void feed() {
System.out.println("書很好!");
}
}
動態代理類:public class ProxyHandler implements InvocationHandler {
private Object sub;
public ProxyHandler(Object obj) {
this.sub = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
System.out.println("買之前先收錢: " + method);
method.invoke(sub, args);
System.out.println("買之後給發票: " + method);
return null;
}
}
該代理類的內部屬性是Object類型,實際使用的時候通過該類的構造方法傳遞進來一個對象。此外,該類還實現了invoke方法,該方法中的method.invoke其實就是調用被代理對象的將要執行的方法,方法參數是sub,表示該方法從屬於sub,通過動態代理類,我們可以在執真實對象的方法前後 加入自己的一些額外方法。public class Client {
public static void main(String[] args) {
Teacher teacher = new Teacher();
InvocationHandler handler = new ProxyHandler(teacher);
Class<?> classType = handler.getClass();
// 下面的代碼一次性生成代理
IConsumer consumer = (IConsumer) Proxy.newProxyInstance(classType.getClassLoader(), teacher.getClass().getInterfaces(),handler);
consumer.buy();
}
}
1)Interface InvocationHandler:
invoke(Object obj,Method method, Object[] args) 參數obj一般是指代理類,method則被代理執行方法,該方法在代理類中動態實現,args爲方法參數
(2).Proxy:動態代理類:
Protected Proxy(InvocationHandler h):構造函數
Static Class getProxyClass (ClassLoader loader, Class[] interfaces):獲得一個代理類,其中loader是類裝載器,interfaces是真實類所擁有的全部接口的數組。
Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理類的一個實例,返回後的代理類可以當作被代理類使用(可使用被代理類的在Subject接口中聲明過的方法)。
所謂Dynamic Proxy是這樣一種class:它是在運行時生成的class,在生成它時你必須提供一組interface給它,然後該class就宣稱它實現了這些 interface。你當然可以把該class的實例當作這些interface中的任何一個來用。當然啦,這個Dynamic Proxy其實就是一個Proxy,它不會替你作實質性的工作,在生成它的實例時你必須提供一個handler,由它接管實際的工作。