1. 程式人生 > >設計模式: 自己手動寫一個代理模式

設計模式: 自己手動寫一個代理模式

代理模式:為另一個物件提供一個替身或佔位符以訪問這個物件。代理模式為另一個物件提供代表,以便控制客戶對物件的訪問,管理訪問的方式有許多種。

遠端代理管理客戶和遠端物件之間的互動。

虛擬代理控制訪問例項化開銷大的物件。

保護代理基於呼叫者控制對物件方法的訪問。

代理模式有許多變體,例如:快取代理、同步代理、防火牆代理、寫入時複製代理。

Java內建的代理支援,可以根據需要動態建立代理,並將所有呼叫分配到所選的呼叫處理器(InvocationHandler)。

下面 的例子是一種保護代理

類圖:


原始碼如下:

package javaproxy;
/**
 * 被代理者介面
 * @author Arvon
 *
 */
public interface PersonBean {
	public String getName();
	public String getGender();
	public String getInterests();
	public int getHotAndNotRating();
	
	
	public void setHotAndNotRating(int rating);
	public void setInterests(String interests);
	public void setName(String name);
	public void setGender(String gender);
}

package javaproxy;

public class PersonBeanImpl implements PersonBean {

	String name;
	String gender;
	String interests;
	int rating, ratingCount =1;
	
	
	
	public PersonBeanImpl(String name, String gender, String interests, int rating) {
		super();
		this.name = name;
		this.gender = gender;
		this.interests = interests;
		this.rating = rating;
	}
	
	
	
	@Override
	public String toString() {
		return "PersonBeanImpl [name=" + name + ", gender=" + gender + ", interests=" + interests + ", rating=" + getHotAndNotRating()
				+ "]";
	}



	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	public String getInterests() {
		return interests;
	}
	public void setInterests(String interests) {
		this.interests = interests;
	}
	@Override
	public int getHotAndNotRating() {
		return ratingCount==0?0:(rating/ratingCount);
	}
	
	public void setHotAndNotRating(int rating){
		this.rating+=rating;
		ratingCount++;
	}
	
	
	
	
	

}
package javaproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * InvocationHandler 負責處理代理類發來的請求(即代理類的呼叫)
 * @author Administrator
 *
 */
public class OwnerInvocationHandler implements InvocationHandler {
	PersonBean person;
	public OwnerInvocationHandler(PersonBean person) {
		super();
		this.person = person;
	}
	/**
	 * Parameters:proxy - the proxy instance that the method was invoked
	 * onmethod - the Method instance corresponding to the interface method
	 * invoked on the proxy instance. The declaring class of the Method object
	 * will be the interface that the method was declared in, which may be a
	 * superinterface of the proxy interface that the proxy class inherits the
	 * method through.args - an array of objects containing the values of the
	 * arguments passed in the method invocation on the proxy instance, or null
	 * if interface method takes no arguments. Arguments of primitive types are
	 * wrapped in instances of the appropriate primitive wrapper class, such as
	 * java.lang.Integer or java.lang.Boolean.Returns:the value to return from
	 * the method invocation on the proxy instance. If the declared return type
	 * of the interface method is a primitive type, then the value returned by
	 * this method must be an instance of the corresponding primitive wrapper
	 * class; otherwise, it must be a type assignable to the declared return
	 * type. If the value returned by this method is null and the interface
	 * method's return type is primitive, then a NullPointerException will be
	 * thrown by the method invocation on the proxy instance. If the value
	 * returned by this method is otherwise not compatible with the interface
	 * method's declared return type as described above, a ClassCastException
	 * will be thrown by the method invocation on the proxy instance.
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException {
		try {
			if(method.getName().startsWith("get"))
				return method.invoke(person, args); //方法的執行者 person  
			else if(method.getName().equals("setHotAndNotRating"))
				throw new IllegalAccessException();
			else if(method.getName().startsWith("set"))
				return method.invoke(person, args); //方法的執行者 person 
		} catch (Exception e) {
//			e.printStackTrace();
			System.out.println("cannot set rating by owner proxy!");
		}
		return null;//如果呼叫其它的方法一律不予處理
	}

}

package javaproxy;

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

public class NonOwnerInvocationHandler implements  InvocationHandler{

	PersonBean person;
	public NonOwnerInvocationHandler(PersonBean person) {
		super();
		this.person = person;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		try {
			if(method.getName().startsWith("get"))
				return method.invoke(person, args); //方法的執行者 person  
			else if(method.getName().equals("setHotAndNotRating"))
				return method.invoke(person, args);
			else if(method.getName().startsWith("set"))//他人不能設定自己的資訊
				throw new IllegalAccessException();
		} catch (Exception e) {
			System.out.println("cannot set infos from nonowner proxy...");
		}
		return null;//如果呼叫其它的方法一律不予處理
	}
}

package javaproxy;

import java.lang.reflect.Proxy;
/**
 * 動態產生代理類
 * @author Administrator
 *
 */
public class ProxyHelper {
	/**
	 * Returns an instance of a proxy class for the specified interfaces that
	 * dispatches method invocations to the specified invocation handler.
	 * @param person
	 * @return
	 */
	public static PersonBean getOwnerProxy(PersonBean person) {
		return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(),
				new OwnerInvocationHandler(person));
	}
	public static PersonBean getNonOwnerProxy(PersonBean person) {
		return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(),
				new NonOwnerInvocationHandler(person));
	}

}


package javaproxy;
/**
 * 測試類
 * @author Administrator
 *
 */
public class ProxyTest {

	public static void main(String[] args) {
		PersonBean person = new PersonBeanImpl("Jay", "F", "Java", 7);
		System.out.println(person);
		 //動態地產生代理類ownerProxy (代理類ownerProxy實現了PersonBean介面)
		PersonBean ownerProxy = ProxyHelper.getOwnerProxy(person);
		System.out.println("Name is "+ownerProxy.getName());
		 //代理類的方法setInterests被呼叫  代理ownerProxy會把這個呼叫轉發給OwnerInvocationHandler
		//ownerProxy 被例項化的時候指定的呼叫處理器是OwnerInvocationHandler
		// 接著 OwnerInvocationHandler 呼叫它自己的invoke方法 
		//OwnerInvocationHandler 可能會轉發給被代理者PersonBean person 處理,如 return method.invoke(person, args); //方法的執行者 person  
		// 也可能做其他的處理 如丟擲異常 
		ownerProxy.setInterests("python");
		System.out.println(person);
		try {
			ownerProxy.setHotAndNotRating(8);
		} catch (Exception e) {
		}
		PersonBean nonOwnerProxy = ProxyHelper.getNonOwnerProxy(person);
		System.out.println("Name is "+nonOwnerProxy.getName());
		try {
			nonOwnerProxy.setHotAndNotRating(9);
			nonOwnerProxy.setInterests("python");
		} catch (Exception e) {
		}
		System.out.println(person);

	}

}

程式的輸出:

PersonBeanImpl [name=Jay, gender=F, interests=Java, rating=7]
Name is Jay
PersonBeanImpl [name=Jay, gender=F, interests=python, rating=7]
cannot set rating by owner proxy!
Name is Jay
cannot set infos from nonowner proxy...
PersonBeanImpl [name=Jay, gender=F, interests=python, rating=8]

相關推薦

設計模式 自己手動一個代理模式

代理模式:為另一個物件提供一個替身或佔位符以訪問這個物件。代理模式為另一個物件提供代表,以便控制客戶對物件的訪問,管理訪問的方式有許多種。 遠端代理管理客戶和遠端物件之間的互動。 虛擬代理控制訪問例項化開銷大的物件。 保護代理基於呼叫者控制對物件方法的訪問。 代理模式有許多

設計模式 自己手動實現一個觀察者設計模式

package rgs name gree 觀察者設計模式 forecast server 它的 upd 觀察者模式: 定義了對象之間的一對多依賴,這樣一來。當一個對象(被觀察者)改變狀態時,它的全部依賴者(觀察者)都會收到通知並自己主動更新。 在觀察者模式中,會

較底層程式設計自己動手一個C語言編譯器

  今天呢,我們就來自己動手編寫一個編譯器,學習一下較為底層的程式設計方式,是一種學習計算機到底是如何工作的非常有效方法。 編譯器通常被看作是十分複雜的工程。事實上,編寫一個產品級的編譯器也確實是一個龐大的任務。但是寫一個小巧可用的編譯器卻不是這麼困難。 祕訣就是首先去找到一個

ROS學習筆記(一)自己動手一個ROS程式

最近老闆安排任務,要把ROS框架在ARM+FPGA平臺上實現。但是使用ROS建立程式步驟繁瑣,所以這次將官方文件上面的Demo簡化寫下來,方便以後檢視。 ROS版本:Hydro Linux版本:Ubuntu12.04 在開始第一個ROS(Robot Operating Sy

自己手動一個簡單的bs結構

拋去web框架,自己手寫一個BS請求響應過程: 自己建立一個資料夾test,包含一個hello.html 和一個webserver.py 自己在html檔案裡面寫一些標籤 下面是webserver.py的主要內容: import os from

多執行緒設計模式第三篇 - 生產者-消費者模式和讀模式

一,生產者-消費者模式         生產者-消費者模式是比較常見的一種模式,當生產者和消費者都只有一個的時候,這種模式也被稱為 Pipe模式,即管道模式。      &nb

設計模式(二)自己動手使用“觀察者模式”實現通知機制

在之前釋出Objective-C系列部落格的時候,其中提到過OC的通知機制,請參考《Objective-C中的老闆是這樣發通知的(Notification)》這篇部落格。在之前關於Notification的部落格中,只介紹了Foundation框架中的通知的使用方式。正如前面部落格中提到的那樣,通知是“一對多

「補課」進行時設計模式(5)——從 LOL 中學習代理模式

![](https://cdn.geekdigging.com/DesignPatterns/java_design_pattern.jpg) ## 1. 前文彙總 [「補課」進行時:設計模式系列](https://www.geekdigging.com/category/%e8%ae%be%e8%ae%

自己動手一個自動登錄腳本gg

簡單 只需要 自己 不同 enum -s class rep 使用 1.下載一個sshpass工具 2.安裝sshpass,安裝到tools文件夾 3.把tools文件夾的路徑加入到/etc/bashrc vim /etc/bashrc

<四>讀<<大話設計模式>>之代理模式

flow 編程 運行 應該 nts popu rac gif 通過 代理模式我想大家即便不熟悉也都聽過吧,從字面意思上看就是替別人幹活的,比方代理商。在項目的實際應用中也有非常多地方用到。比方spring通過代理模式生成對象等。 代理模式的書

傳智自己簡單實現一個struts2框架的demo

throws for request 運行 本地化 color ray run main struts2的結構圖: 代碼實現: 組織結構: 主要代碼: package cn.itcast.config; import org.apache.log4j.Logg

用JAVA一個阿裏雲VPC Open API調用程序

外部jar包 ef7 dac java 方式 命令 pro ng- 自動化管理 用JAVA寫一個阿裏雲VPC Open API調用程序 摘要:用JAVA拼出來Open API的URL 引言 VPC提供了豐富的API接口,讓網絡工程是可以通過API調用的方式

python 1-2+3-4....99=? 這裏的題,我看到別人的寫法,五花八門的,自己一個

blog sta 裏的 and str 想象力 pos 問題 就是 f = ""s = ""i = 1sum = 0while i < 100:   if i %2 == 1 and i < 99:     f = "-"

設計模式學習筆記(4)——建造者模式

receiver temp pla his AI 技術 bubuko 電子 中一 設計模式:學習筆記(4)——建造者模式 概述 建造者模式   建造者模式是較為復雜的創建型模式,它將客戶端與包含多個組成部分(或部件)的復雜對象的創建過程分離,客戶端無須知道復雜對象的內部組成

設計模式學習筆記(6)——抽象工廠模式

方法 組成 pat AR ID 指定 ride 抽象工廠模式 nds 設計模式:學習筆記(6)——抽象工廠模式 快速開始 介紹   抽象工廠模式(Abstract Factory Pattern)是圍繞一個超級工廠創建其他工廠。該超級工廠又稱為其他工廠的工廠。這種類型的設計

設計模式學習筆記(10)——適配器模式

light .com rgs strong 接口 可能 兼容 不能 pan 設計模式:學習筆記(10)——適配器模式 引入適配器模式 我們身邊的適配器 適配器是什麽,你一定不難理解,因為現實中到處都是。比方說:如果你需要在歐洲國家使用美國制作的筆記本電腦,你可能需要一個交

自己動手一個單鏈表

兩個指針 isl linklist nextn mob 內部 數組 nds pty 文章有不當之處,歡迎指正,如果喜歡微信閱讀,你也可以關註我的微信公眾號:好好學java,獲取優質學習資源。 一、概述 單向鏈表(單鏈表)是鏈表的一種,其特點是鏈表的鏈接方向是單向的,對鏈表

【原創】自己動手一個服務網關

exception 負責 lis world 前置 create ble ddr load 引言 什麽是網關?為什麽需要使用網關? 如圖所示,在不使用網關的情況下,我們的服務是直接暴露給服務調用方。當調用方增多,勢必需要添加定制化訪問權限、校驗等邏輯。當添加API網關後,

設計模式裝飾器(Decorator)模式

讓我 分享圖片 底部 .com 一件事 輸出 PE 新的 int 設計模式:裝飾器(Decorator)模式 一、前言 裝飾器模式也是一種非常重要的模式,在Java以及程序設計中占據著重要的地位。比如Java的數據流處理,我們可能看到數據流經過不同的類的包裝和包裹,最

設計模式觀察者(Observer)模式

image 強制轉換 trace vat PE sta obs observer -a 設計模式:觀察者(Observer)模式 一、前言 觀察者模式其實最好的名稱應該是“發布訂閱”模式,和我們現在大數據之中的發布訂閱方式比較類似,但是也有區別的地方,在上一個設計模式,