參考的資料:
http://blog.csdn.net/jiuqiyuliang/article/details/38423811
http://www.360doc.com/content/14/0801/14/1073512_398598312.shtml
代理模式:由代理對象持有原對象。在代理對象中做的操作實際上都是由原對象來執(zhí)行的。
1.代理模式可以動態(tài)在真實方法被調(diào)用前添加一些代碼。
2.代理模式更加靈活,根據(jù)傳入不同的真實對象,去執(zhí)行不同的策略,達(dá)到同一個結(jié)果。
靜態(tài)代理:
1.需要一個統(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.原對象實現(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)然還可以由另一個實現(xiàn)
package com.liang.pattern;
public class UserManagerImpl2 implements UserManager {
........
}
3.代理對象實現(xiàn)接口,并且持有原對象。
可以看到代理類中所有的方法,實際上都是執(zhí)行的原函數(shù)的方法
package com.liang.pattern;
public class UserManagerImplProxy implements UserManager {
private UserManager userManager; //持有原對象
public UserManagerImplProxy(UserManager userManager){
this.userManager = userManager;
}
public void addUser(String userId, String userName) {
//在真實的方法調(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();
//失敗時,打印失敗信息
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","于亮");
//同樣我們可以傳入UserManagerImpl2,實現(xiàn)依賴注入
UserManager userManager = new UserManagerImplProxy(new UserManagerImpl2());
userManager.addUser("001","于亮");
**代理模式很靈活,但同時由于接口的關(guān)系,一種代理類,只能代理一組同樣實現(xiàn)了該接口的真實類。這樣可能造成代理類過多,爆炸。
動態(tài)代理
參考資料:http://blog.csdn.net/jiuqiyuliang/article/details/38423811
1、通過實現(xiàn)InvocationHandler接口創(chuàng)建自己的調(diào)用處理器 IvocationHandler handler = new InvocationHandlerImpl(...);
2、通過為Proxy類指定ClassLoader對象和一組interface創(chuàng)建動態(tài)代理類
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});
3、通過反射機(jī)制獲取動態(tài)代理類的構(gòu)造函數(shù),其參數(shù)類型是調(diào)用處理器接口類型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4、通過構(gòu)造函數(shù)創(chuàng)建代理類實例,此時需將調(diào)用處理器對象作為參數(shù)被傳入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
為了簡化對象創(chuàng)建過程,Proxy類中的newInstance方法封裝了2~4,只需兩步即可完成代理對象的創(chuàng)建。
生成的ProxySubject繼承Proxy類實現(xiàn)Subject接口,實現(xiàn)的Subject的方法實際調(diào)用處理器的invoke方法,而invoke方法利用反射調(diào)(根據(jù)傳入的對象,以及參數(shù))調(diào)用被代理對象的的方法(Object result=method.invoke(proxied,args))

如果我們在操作真實對象之前不做任何操作,或者都做統(tǒng)一的處理(比如加日志。),那么不管任何真實類都可以用一個動態(tài)代理類來操作,避免了代理類的爆炸

使用:
