代理模式在 java 開發中是一種比較常見的設計模式。設計目的在爲服務類與客戶類之間插入其餘功能,插入的功能對於調用者是透明的,起到假裝控制的做用,如租房的例子房客、中介、房東。對於代理模式中即:客戶類、代理類、委託類(被代理類)。java
代理模式的兩個設計原則:設計模式
1.代理類與委託類具備類似的行爲(共同)數組
2.代理類加強委託類的行爲ide
Uml簡圖以下:this
爲某個對象提供一個代理,代理角色固定,以控制對這個對象的訪問。代理類和委託類有共同的父類和父接口,這樣在任何使用委託類對象的地方均可以用代理對象代替。代理類負責請求的預處理、過濾、將請求分派給委託類處理、以及委託類執行完請求後的後續處理。url
/** * * 接口 抽象角色 * 定義行爲 */ public interface Marry { public void toMarry(); }
/** * 目標類 真實角色 */ public class You implements Marry{ @Override public void toMarry() { System.out.println("等了這麼久,終於等到你。。。 "); } }
/** * * 代理類 代理角色 * 1.與目標角色實現共同接口 * 2.持有目標類的引用 * 3.加強目標角色行爲 */ public class MarryCompany implements Marry{ // 目標角色引用 private Marry target; public MarryCompany(Marry target) { this.target = target; } public void before(){ System.out.println("婚禮現場緊張佈置中......"); } @Override public void toMarry() { before(); target.toMarry(); after(); } public void after(){ System.out.println("恭喜您成功進入人生第二階段....."); } }
public class Test { public static void main(String[] args) { // 構造代理角色同時傳入真實角色 MarryCompany marryCompany=new MarryCompany(new You()); marryCompany.toMarry(); } }
由於靜態代理對於代理的角色是固定的,如 dao 層 20 個 dao 類,若是要對方法的訪問權限進行代理,此時須要建立 20 個靜態代理角色,引發類爆炸,沒法知足生產上的須要,因而就催生了動態代理的思想。 設計
相比於靜態代理,動態代理在建立代理對象上更加的靈活,它會根據須要經過反射機制在程序運行期動態的爲目標對象建立代理對象,代理的行爲能夠代理多個方法, 即知足生產須要的同時又達到代碼通用的目的。動態代理的兩種實現方式:代理
對於 jdk 動態代理實現方式比較複雜,回調方式實現底層原理參考: http://rejoy.iteye.com/blog/1627405code
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** *jdk 動態代理 */ public class JdkHandler implements InvocationHandler{ // 目標類 private Object target; public JdkHandler(Object target) { this.target = target; } /** * 程序運行期動態建立代理角色 * @return */ public Object getProxy(){ /** * 獲取代理對象 * 1.類加載器 * 2.目標類 實現的接口數組 * 3.當前類 * @return */ return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } public void before(){ System.out.println("婚禮現場緊張佈置中......"); } @Override//InvocationHandler內部參數 當前目標類的方法 參數 public Object invoke(Object proxy, Method method, Object[] args)throws Throwable { before();//加強真實角色行爲 Object result= method.invoke(target, args);// 執行真實角色方法 after();//加強真實角色行爲 return result; } public void after(){ System.out.println("恭喜您成功進入人生第二階段....."); } }
code generator library ,操做字節碼。 與 jdk 提供的代理區別,Proxy:委託類必須有接口,製做過程比較快,執行慢;cglib:委託類能夠沒有接口,繼承的思惟來實現類似性,製做代理過程比較慢,執行快。主要解決沒有接口類的代理實現。 xml
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CglibInterceptor implements MethodInterceptor { private Object target; public CglibInterceptor(Object target) { this.target = target; } // 運行期動態建立代理類 public Object getProxy(){ Enhancer enhancer=new Enhancer(); //設置父類 class enhancer.setSuperclass(target.getClass()); //設置回調對象實現接口的類 enhancer.setCallback(this); return enhancer.create(); } public void before(){ System.out.println("婚禮現場緊張佈置中......"); } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2,MethodProxy arg3) throws Throwable { before();//加強真實角色行爲 Object result= arg3.invoke(target, arg2); after();//加強真實角色行爲 return result; } public void after(){ System.out.println("恭喜您成功進入人生第二階段....."); } }
「可見性」表示該屬性對類外的元素是否可見,包括公有(Public)、私有(Private)、受保護(Protected)和朋友(Friendly)4 種,
在類圖中分別用符號+、-、#、~表示 。
UML 中的類圖有如下幾種關係:
依賴關係(帶箭頭虛線)、
關聯關係(帶X個箭頭的實線)、
聚合關係(帶空心菱形的實線)、
組合關係(帶實心菱形的實線)、
泛化關係(帶空心三角箭頭的實線)、
實現關係(帶空心三角箭頭的虛線)、
其中泛化和實現的耦合度相等,它們是最強的。