代理模式是一種效率非常高的模式,其定義如下:提供一種代理以控制對這個對象的訪問。
代理模式也叫委托模式,它是一項基本設計技巧。許多其他的設計模式,如狀態模式,策略模式,訪問者模式本質上是在更特殊的場合上采用了委托模式,代理模式在日常的使用中能夠提供更好的訪問控制。
1: 抽象角色
抽象主題角色類可以是一個接口,是一個普通的業務類型定義,無特殊要求。
2:具體角色
也叫被委托角色,這個角色才是真正干活的角色,是業務邏輯的具體執行者
3:代理主題角色
也叫做委托類,代理類,它負責對真實角色的應用,把所有抽象主題類定義的方法限制委托給真實角色實現,並且在真實主題角色
處理完畢前後做預處理和善後工作。
--------------------------------------分割線 --------------------------------------
編寫高質量代碼 改善Java程序的151個建議 PDF高清完整版 http://www.linuxidc.com/Linux/2014-06/103388.htm
Java 8簡明教程 http://www.linuxidc.com/Linux/2014-03/98754.htm
Java對象初始化順序的簡單驗證 http://www.linuxidc.com/Linux/2014-02/96220.htm
Java對象值傳遞和對象傳遞的總結 http://www.linuxidc.com/Linux/2012-12/76692.htm
Java對象序列化ObjectOutputStream和ObjectInputStream示例 http://www.linuxidc.com/Linux/2012-08/68360.htm
--------------------------------------分割線 --------------------------------------
定義一個接口:
package com.zzu.proxy;
public interface Movable {
void run();
}
實現類
package com.zzu.proxy;
public class Tank implements Movable{
@Override
public void run() {
try {
System.out.println("Tank is running.....");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
代理類
package com.zzu.proxy;
public class TankLogProxy implements Movable{
public TankLogProxy(Movable t) {
super();
this.t = t;
}
Movable t;
@Override
public void run() {
System.out.println("start log...");
t.run();
System.out.println("end log....");
}
}
另外一個代理類
package com.zzu.proxy;
public class TankTimeProxy implements Movable{
public TankTimeProxy(Movable t) {
super();
this.t = t;
}
Movable t;
@Override
public void run() {
System.out.println("time start...");
long start = System.currentTimeMillis();
t.run();
long end = System.currentTimeMillis();
System.out.println("time: "+(end - start));
}
}
client類
package com.zzu.proxy;
public class Client {
public static void main(String[] args) {
Movable m = new Tank();
TankLogProxy tlp = new TankLogProxy(m);
TankTimeProxy ttp = new TankTimeProxy(tlp);
Movable b = ttp;
b.run();
}
}
其實代理真正有意思的地方還是在於動態代理。下面說說動態代理的內在原理
動態代理:它和普通代理的不同地方在於,他在實現階段不用關心代理誰,而是在運行階段來指定哪一個對象。
它的實現實際上是通過JDK提供的 InvocationHandler,下面我們通過代碼的形式來研究一下動態代理的內在執行機制
我們先定義一個接口:
package dynamic;
public interface Subject {
// 業務操作
public void doSomething(String str);
//增加一個方法
public void doGirl();
}
接口的實現
package dynamic;
public class RealSubject implements Subject {
@Override
public void doSomething(String str) {
System.out.println("do some things -->>> " + str);
}
@Override
public void doGirl() {
System.out.println("to find a girl --->>>>> ");
}
}
動態代理的handler類
package dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 其中的InvocationHandler是JDK提供的動態代理的接口,其中的invoke方法是InvocationHandler必須實現的,它完成對真實方法的調用,即所有的真實方法調用都交給handler來接管
* @author Administrator
*
*/
public class MyInvocationHandler implements InvocationHandler {
// 被代理的對象
private Object target = null;
// 通過構造函數傳遞一個對象
public MyInvocationHandler(Object _obj) {
this.target = _obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return method.invoke(this.target, args);
}
}
動態代理類
package dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class DynamicProxy<T> {
public static <T> T newProxyInstance(ClassLoader loader,
Class<?>[] interfaces, InvocationHandler h) {
// 尋找joinPoint連接點,AOP框架使用元數據定義
if (true) {
// 執行前一個通知
new BeforeAdvice().exec();
}
return (T) Proxy.newProxyInstance(loader, interfaces, h);
}
}
動態代理的場景類
package dynamic;
import java.lang.reflect.InvocationHandler;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
//定義一個主題
Subject subject = new RealSubject();
//定義一個handler
InvocationHandler handler = new MyInvocationHandler(subject);
//定義主題的代理
Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), handler);
//代理的行為,
proxy.doSomething("Finish");
proxy.doGirl();
}
}
動態代理實際上個人感覺和普通代理沒什麼區別,實際上的作用就是在不改變代碼的情況下增強或控制對象的行為,
動態代理實現代理的職責,業務邏輯實現相關的邏輯功能,兩者之間沒有必然的相互耦合的關系。