Java代理模式(靜態代理)

代理模式是通過創建一個代理對象,使用這個代理對象代替實際對象。對於客戶端而言,得到代理對象於操作而言沒有任何影響。

當客戶端操作代理對象時,實際上操作會由實際對象完成。即客戶端操作代理對象,代理對象操作實際對象,而代理對象在操作實際對象時,可以添加額外的操作實現懶加載,權限限定等一系列額外操作。

代理分類:

1、  虛代理:根據需要創建開銷很大的對象,而該對象只有在真正需要的時候纔會被真正創建。實際應用------懶加載。

2、  遠程代理:用來在不同的地址空間表示同一個對象。實際應用------RMI技術

3、  Copy-on-wirte:只有當對象確實改變了,纔會拷貝一個目標對象。

4、  保護代理:控制對原始對象的訪問。


下文則從最簡單的靜態代理開始講解java中的代理模式:

以生活中銷售手機爲例,廠家生產手機,經銷商從廠家拿貨銷售給客戶。而在這個過程中,經銷商就是廠家的代理。可以在廠家銷售過程中增加一系列加價,滿減等活動。而針對客戶,買手機這一操作並沒有因爲是從經銷商處購買收到影響。而經銷商也是在廠家銷售的基礎上增加其他活動,完成整個代理。


代碼實例:

1、公用接口

public interface SellProduct {

	public int SellPhone(String phoneName);
}

2、實際對象廠家():

public class Producer implements SellProduct{


	/**
	 * 模擬廠家定價
	 */
	@Override
	public int SellPhone(String phoneName) {
		// TODO Auto-generated method stub
		int price = 0;
		switch (phoneName) {
		case "iphone":
			price = 6000;
			break;
		case "mi":
			price = 2499;
		default:
			break;	
		}
		System.out.println("銷售手機:"+phoneName+",價格:"+price);
		return price;
	}

}

3、代理對象(經銷商):

public class Dealer implements SellProduct{

	private Producer producer;
	
	public Dealer(Producer producer) {
		this.producer = producer;
	}
	/**
	 * 經銷商不需要知道廠家如何定價,只要在出廠價基礎上加價即可
	 */
	@Override
	public int SellPhone(String phoneName) {
		int price = producer.SellPhone(phoneName)+200;	
		System.out.println("銷售手機:"+phoneName+",價格:"+price);
		return price;
	}

}

4、客戶:

public class Client {

	public static void main(String []args){

		SellProduct sell = new Dealer(new Producer());
		sell.SellPhone("iphone");
	}
}

運行結果:

銷售手機:iphone,價格:6200

以下介紹兩種其他常用的代理模式:

一:虛代理(實際運用與懶加載):

在數據庫中,往往需要一個對象有很多個屬性,而一次性加載所有屬性是對內存的極大浪費。如果我們第一次只查詢必要的數據,而其他數據等到需要時再查詢,無疑會大大減小內存的消耗。

1、接口:

public interface UserModel {

	public int getId();
	
	public void setId(int id);
	
	public String getName();
	
	public void setName(String name);
}

2、實際對象:

public class UserModelImpl implements UserModel {

	private int id;
	private String name;

	@Override
	public int getId() {
		// TODO Auto-generated method stub
		return id;
	}

	@Override
	public void setId(int id) {
		// TODO Auto-generated method stub
		this.id = id;
	}

	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return name;
	}

	@Override
	public void setName(String name) {
		this.name = name;

	}

}


3、代理對象:

public class ProxyModel implements UserModel{

	private UserModelImpl userModel;
	
	private boolean isLoad = false;
	
	public ProxyModel(UserModelImpl userModel){
		this.userModel = userModel;
	}

	@Override
	public int getId() {
		// TODO Auto-generated method stub
		return userModel.getId();
	}

	@Override
	public void setId(int id) {
		// TODO Auto-generated method stub
		userModel.setId(id);
	}

	@Override
	public String getName() {
		// TODO Auto-generated method stub
		if(!this.isLoad){
			reload();
			this.isLoad = true;
		}
		return userModel.getName();
	}

	@Override
	public void setName(String name) {
		// TODO Auto-generated method stub
		userModel.setName(name);
	}
	/**
	 * 重新從數據庫中獲取name注入實際對象
	 */
	private void reload(){
		String name = getNameFromSQL();
		System.out.println("重新從數據庫加載數據");
		userModel.setName(name);
	}
	/**
	 * 模擬從數據庫獲取name操作
	 * @return
	 */
	private String getNameFromSQL(){
		return "simulation";
	}
}

4、客戶使用:

public class Client {

	/**
	 * 模擬從數據庫中查詢,因爲不需要知道其他屬性,只注入id即可
	 * @param usermodel
	 */
	private static void SQLQuery(UserModel usermodel){
		
		usermodel.setId(1);
	}
	
	public static void main(String []args){
		ProxyModel proxy = new ProxyModel(new UserModelImpl());
		SQLQuery(proxy);
		System.out.println("id:"+proxy.getId());
		System.out.println("name:"+proxy.getName());
	}
}

運行結果:
id:1
重新從數據庫加載數據
simulation


二 保護代理:

控制原始對象訪問的代理。

1、接口:

public interface OAOperate {

	
	public void add();
	
	public void select();
	
	public void delete();
}

2、原始對象:

public class OAOperater implements OAOperate{

	private String name;
	
	private int flag;
	
	public OAOperater(String name,int flag) {
		this.name = name;
		this.flag = flag;
	}
	
	public int getFlag(){
		return this.flag;
	}
	
	@Override
	public void add() {
		//省略相應操作
	}

	@Override
	public void select() {
		//省略相應操作
	}

	/**
	 * delete需要權限設置
	 */
	@Override
	public void delete() {
		//省略相應操作
		System.out.println("刪除操作");
	}

}

3、代理對象:

public class OAProxy implements OAOperate {

	private OAOperater operate;

	public OAProxy(OAOperater operate) {
		this.operate = operate;
	}

	@Override
	public void add() {
		// TODO Auto-generated method stub

	}

	@Override
	public void select() {
		// TODO Auto-generated method stub

	}

	@Override
	public void delete() {
		// TODO Auto-generated method stub
		if (operate.getFlag() != 4) {
			System.out.println("權限不足,不能修改");
		} else {
			operate.delete();
		}

	}

}

4、客戶:

public class Client {

	public static void main(String []args){
		OAOperate operate = new OAProxy(new OAOperater("xiaoming", 3));
		operate.delete();
		
		OAOperate operater = new OAProxy(new OAOperater("paditang", 4));
		operater.delete();
	}
}

運行結果:

權限不足,不能修改
刪除操作




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