Java實戰(二)—代理模式


一、背景


   當我們系統中每個方法都需要相同的功能時,比如日誌、事務……;我們之前一直就是將相應都重新寫一遍。如果我們共同的方法出現了問題,所有用到它的方法都必須進行修改,系統維護起來困難,並且不符合OCP原則。那該怎樣去做?

   常規編程:重複代碼寫到每個方法中

   


二、學習軌跡


   第一次學習:設計模式(九)-代理模式(結構型)  懵懂中繼續學習,理解的比較淺顯

   第二次學習:重溫設計模式(一)—代理模式   現在看來有些理解的或是淺顯,或是真的錯了;但沒之前的糊里糊塗,哪有現在的清晰思路

   第三次學習:項目實戰(二)—代理模式 結合項目發現了原來代理是這麼回事,瞭解了動態代理是AOP的實現原理,其中invoke相當於filter(統一進行控制)

 

三、定義


   代理模式給某個對象提供了一個代理對象,並由代理對象控制對原有對象的引用    

          

注:

客戶端不再操作真實對象,直接與代理交互

代理與真實對象接口一致,代理類控制真實對象的訪問

實例:

   廠家、代理商、客戶(代理商只負責賣東西,不負責生產)


四、靜態代理  

     將相同代碼轉移到代理上,易維護,不需要修改真實對象(代理類進行控制)

           

     調用過程:

 

2、優缺點:


   優點:將相同代碼轉移到代理上,修改共同代碼時,不需要修改真實對象,複合OCP原則;系統更加靈活

   缺點:未解決代碼重複問題,代理上每個方法依舊有相同代碼


3、代碼實例

/**
 * 接口UserManager
 *@author 高曉青  
 * @date 創建時間:2015-3-6 下午8:09:33 
 */
public interface UserManager {
	public void addUser(String userId,String userName);
	
	public void delUser(String userId);
	
	public String ModifyUser(String userId,String userName);
	
	public void findUser(String userId);
	
}
(2)具體實現累
package com.bjpowernode.pattern;
/**
 * 
 *@author 高曉青  
 * @date 創建時間:2015-3-6 下午8:11:55 
 */
public class UserManagerImpl implements UserManager {

	public void addUser(String userId, String userName) {
		System.out.println("UserManagerImpl.addUser() userId-->"+userId);
	}

	public void delUser(String userId) {
		System.out.println("UserManagerImpl.delUser() userId-->"+userId);
	}

	public String ModifyUser(String userId, String userName) {
		System.out.println("UserManagerImpl.ModifyUser() userId-->"+userId);
		return "張三";
	}

	public void findUser(String userId) {
		System.out.println("UserManagerImpl.findUser() userId-->"+userId);
	}
}

(3)代理類
package com.bjpowernode.pattern;
/**
 * 代理類
 *@author 高曉青  
 * @date 創建時間:2015-3-6 下午8:21:34 
 */
public class UserManagerImplProxy implements UserManager {
	private UserManager userManager;
	
	//對真實對象的引用
	public UserManagerImplProxy(UserManager userManager) {
		this.userManager=userManager;
	}

	public void addUser(String userId, String userName) {
		try {
			//重複的代碼
			System.out.println("Start-->>addUser() useId-->>"+userId );
			//調用真實對象的方法
			userManager.addUser(userId, userName);
			//重複的代碼
			System.out.println("success-->>addUser()");
			
		} catch (Exception e) {
			e.printStackTrace();
			//重複的代碼
			System.out.println("error-->>addUser()");
		}
	}

	public void delUser(String userId) {
		// TODO Auto-generated method stub

	}

	public String ModifyUser(String userId, String userName) {
		// TODO Auto-generated method stub
		return null;
	}

	public void findUser(String userId) {
		// TODO Auto-generated method stub

	}
}
(4)客戶端
package com.bjpowernode.pattern;

public class Client {
	/**
	 * 客戶端
	 * @param args
	 */
	public static void main(String[] args) {
		//客戶端只與代理聯繫
		UserManager userManager = new UserManagerImplProxy(new UserManagerImpl());
		userManager.addUser("0001", "張三");
	}

}




五、動態代理


   解決了代碼重複問題


 

前提:代理類與普通類實現相同的接口


1、優缺點

     優點:消除了重複代碼

     不足:使用了反射,損耗效率


2、代碼實例

     JDK動態代理只能對實現了接口的類進行代理,採用JDK動態代理必須實現InvocationHanlder接口,採用Proxy類創建相應的代理類


     <1 invoke方法:在代理實例上處理方法調用並返回結果

   public Object invoke(Object proxy, Method method,Object[] arguments)

   Extract the appropriate property value from the eventand pass it to the action associated with this EventHandler.

     <2 Proxy類:用來創建冬天代理類和實例的靜態方法,會根據接口在內存中建立類

<span style="font-family:KaiTi_GB2312;font-size:14px;"><span style="background-color: rgb(255, 255, 255);">    </span></span><pre name="code" class="csharp">(1)接口UserManager
package com.bjpowernode.pattern;
/**
 * 接口UserManager
 *@author 高曉青  
 * @date 創建時間:2015-3-6 下午8:09:33 
 */
public interface UserManager {
	public void addUser(String userId,String userName);
	
	public void delUser(String userId);
	
	public String ModifyUser(String userId,String userName);
	
	public void findUser(String userId);
	
}
(2)具體實現累
package com.bjpowernode.pattern;
/**
 * 
 *@author 高曉青  
 * @date 創建時間:2015-3-6 下午8:11:55 
 */
public class UserManagerImpl implements UserManager {

	public void addUser(String userId, String userName) {
		System.out.println("UserManagerImpl.addUser() userId-->"+userId);
	}

	public void delUser(String userId) {
		System.out.println("UserManagerImpl.delUser() userId-->"+userId);
	}

	public String ModifyUser(String userId, String userName) {
		System.out.println("UserManagerImpl.ModifyUser() userId-->"+userId);
		return "張三";
	}

	public void findUser(String userId) {
		System.out.println("UserManagerImpl.findUser() userId-->"+userId);
	}
}
(3)代理類
package com.bjpowernode.pattern;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class LogHandler implements InvocationHandler {
	
	private Object targetObject;
	
	//對誰生成代理,將相應的目標傳入,返回Object
	public Object newProxyInstance(Object targetObject) {
		this.targetObject = targetObject;
		//根據傳入對象,生成代理對象
		//getClassLoader()與目標使用加載器一致
		//interface獲得對象實現的接口,根據接口創建代理類,但方法爲空 
		//this:實現invocationhandler類,指現在這個類
		return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
	<span style="white-space:pre">	</span> targetObject.getClass().getInterfaces(), this);
	}
	
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		//公共方法
		System.out.println("start-->>" + method.getName());
		
		//獲得目標方法的參數
		for (int i=0; i<args.length; i++) {
			System.out.println(args[i]);
		}
		
		Object ret = null;
		try {
			//調用目標方法
			ret = method.invoke(targetObject, args);
			
			//公共方法
			System.out.println("success-->>" + method.getName()); 
		}catch(Exception e) {
			e.printStackTrace();
			
			//公共方法
			System.out.println("error-->>" + method.getName());
			throw e;
		}
		return ret;
	}
}
(4)客戶端
package com.bjpowernode.pattern;
/**
 * 
 *@author 高曉青  
 * @date 創建時間:2015-3-6 下午8:15:25 
 */
public class Client {

	/**
	 * @param args
	 */
	public static void main(String[] args) {		
		LogHanlder logHanlder=new LogHanlder();
		UserManager userManager=(UserManager)logHanlder.newProxyInstance(new UserManagerImpl());
		
		//調用代理上的方法(內存中)調用invoke方法
		userManager.addUser("0001", "張三");		
	}
}

         代理模式的引入,使系統更加靈活。SpringAOP的實現原理是動態代理,具體AOP究竟是什麼樣的!接下來的學習中再深入。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章