參考的資料:
http://blog.csdn.net/jiuqiyuliang/article/details/38423811
http://www.360doc.com/content/14/0801/14/1073512_398598312.shtml
代理模式:由代理對(duì)象持有原對(duì)象辜腺。在代理對(duì)象中做的操作實(shí)際上都是由原對(duì)象來(lái)執(zhí)行的氧猬。
1.代理模式可以動(dòng)態(tài)在真實(shí)方法被調(diào)用前添加一些代碼。
2.代理模式更加靈活,根據(jù)傳入不同的真實(shí)對(duì)象,去執(zhí)行不同的策略,達(dá)到同一個(gè)結(jié)果。
靜態(tài)代理:
1.需要一個(gè)統(tǒng)一的接口,接口規(guī)定了要執(zhí)行什么方法纵东。
package com.liang.pattern;
public interface UserManager {
public void addUser(String userId,String userName);
public void delUser(String userId);
public void modifyUser(String userId,String userName);
public String findUser(String userId);
}
2.原對(duì)象實(shí)現(xiàn)接口
package com.liang.pattern;
public class UserManagerImpl implements UserManager {
public void addUser(String userId, String userName) {
try{
System.out.println("UserManagerImpl.addUser() userId-->>" + userId);
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException();
}
}
public void delUser(String userId) {
System.out.println("UserManagerImpl.delUser() userId-->>" + userId);
}
public String findUser(String userId) {
System.out.println("UserManagerImpl.findUser() userId-->>" + userId);
return "于亮";
}
public void modifyUser(String userId, String userName) {
System.out.println("UserManagerImpl.modifyUser() userId-->>" + userId);
}
}
當(dāng)然還可以由另一個(gè)實(shí)現(xiàn)
package com.liang.pattern;
public class UserManagerImpl2 implements UserManager {
........
}
3.代理對(duì)象實(shí)現(xiàn)接口,并且持有原對(duì)象啥寇。
可以看到代理類中所有的方法偎球,實(shí)際上都是執(zhí)行的原函數(shù)的方法
package com.liang.pattern;
public class UserManagerImplProxy implements UserManager {
private UserManager userManager; //持有原對(duì)象
public UserManagerImplProxy(UserManager userManager){
this.userManager = userManager;
}
public void addUser(String userId, String userName) {
//在真實(shí)的方法調(diào)用之前,加入其它操作辑甜,比如:
//記錄日志等操作或打印輸入?yún)?shù)
System.out.println("start-->>addUser() userId-->>" + userId);
try{
userManager.addUser(userId, userName);
//執(zhí)行成功衰絮,打印成功信息
System.out.println("success-->>addUser()");
}catch(Exception e){
e.printStackTrace();
//失敗時(shí),打印失敗信息
System.out.println("error-->>addUser()");
//throw new RuntimeException();
}
}
public void delUser(String userId) {
//同上磷醋,略
userManager.delUser(userId);
}
public String findUser(String userId) {
//同上猫牡,略
userManager.findUser(userId);
return null;
}
public void modifyUser(String userId, String userName) {
//同上,略
userManager.modifyUser(userId, userName);
}
}
4.客戶端的調(diào)用
UserManager userManager = new UserManagerImplProxy(new UserManagerImpl());
userManager.addUser("001","于亮");
//同樣我們可以傳入U(xiǎn)serManagerImpl2邓线,實(shí)現(xiàn)依賴注入
UserManager userManager = new UserManagerImplProxy(new UserManagerImpl2());
userManager.addUser("001","于亮");
**代理模式很靈活淌友,但同時(shí)由于接口的關(guān)系,一種代理類震庭,只能代理一組同樣實(shí)現(xiàn)了該接口的真實(shí)類瑰抵。這樣可能造成代理類過(guò)多,爆炸器联。
動(dòng)態(tài)代理
參考資料:http://blog.csdn.net/jiuqiyuliang/article/details/38423811
1二汛、通過(guò)實(shí)現(xiàn)InvocationHandler接口創(chuàng)建自己的調(diào)用處理器 IvocationHandler handler = new InvocationHandlerImpl(...);
2、通過(guò)為Proxy類指定ClassLoader對(duì)象和一組interface創(chuàng)建動(dòng)態(tài)代理類
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});
3主籍、通過(guò)反射機(jī)制獲取動(dòng)態(tài)代理類的構(gòu)造函數(shù)习贫,其參數(shù)類型是調(diào)用處理器接口類型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4逛球、通過(guò)構(gòu)造函數(shù)創(chuàng)建代理類實(shí)例千元,此時(shí)需將調(diào)用處理器對(duì)象作為參數(shù)被傳入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
為了簡(jiǎn)化對(duì)象創(chuàng)建過(guò)程,Proxy類中的newInstance方法封裝了2~4颤绕,只需兩步即可完成代理對(duì)象的創(chuàng)建幸海。
生成的ProxySubject繼承Proxy類實(shí)現(xiàn)Subject接口,實(shí)現(xiàn)的Subject的方法實(shí)際調(diào)用處理器的invoke方法奥务,而invoke方法利用反射調(diào)(根據(jù)傳入的對(duì)象物独,以及參數(shù))調(diào)用被代理對(duì)象的的方法(Object result=method.invoke(proxied,args))
如果我們?cè)诓僮髡鎸?shí)對(duì)象之前不做任何操作,或者都做統(tǒng)一的處理(比如加日志氯葬。)挡篓,那么不管任何真實(shí)類都可以用一個(gè)動(dòng)態(tài)代理類來(lái)操作,避免了代理類的爆炸
使用: