エージェント(Proxy)モード【構造モード第1編】


プロキシ(Proxy)モード
は、オブジェクトの構造モードです.プロキシモードは、オブジェクトにプロキシオブジェクトを提供し、プロキシオブジェクトによって元のオブジェクトへの参照を制御します.
一、代理の種類:
使用目的に応じて区分される場合、エージェントには次のようなものがあります.
1.リモートエージェント:異なるアドレス空間にあるオブジェクトにローカル代表オブジェクトを提供する.この異なるアドレス空間は本機械で、
別の機械でもいいです.リモートエージェントは大使(Ambassador)とも呼ばれます.
2、仮想(Virtual)エージェント:必要に応じてリソース消費量の大きいオブジェクトを作成し、必要に応じてオブジェクトが実際に作成されるようにします.
3、Copy-on-Writeエージェント:仮想エージェントの一種で、クライアントが必要とするときだけ、本当に行動するようにコピー(クローン)を遅らせる.
4、保護(Protect or Access)エージェント:1つのオブジェクトへのアクセスを制御し、必要に応じて異なるユーザーに異なるレベルの使用権限を提供することができる.
5、Cache(キャッシュ)エージェント:複数のクライアントがこれらの結果を共有できるように、あるターゲット操作の結果に一時的な記憶領域を提供する.
6、ファイアウォール(Firewall)エージェント:悪意のあるユーザーに近づかないようにターゲットを保護する.
7、Synchronization(Synchronization)エージェント:競合せずに複数のユーザーが同時に1つのオブジェクトを使用できるようにします.
8、スマートリファレンス(Smart Reference)エージェント:オブジェクトが参照されると、このオブジェクトに対して呼び出された回数を記録するなど、追加の操作が提供されます.
二、代理モードの構造:
エージェント・モードの役割は次のとおりです.
1、抽象テーマの役割:真実テーマと代理テーマの共通インタフェースを宣言して、これによって真実テーマを使用できる場所ですべて代理テーマを使用することができる
2、代理テーマロール:代理テーマロールの内部に真実テーマへの参照が含まれているので、いつでも真実テーマオブジェクトを操作できる.
エージェントトピックロールは、実際のトピックロールと同じインタフェースを提供し、いつでも実際のマスターに代わることができます.
実際のトピックへの参照を制御し、必要に応じて実際のトピックオブジェクトを作成します(および実際のトピックオブジェクトを削除します).
プロキシロールは、通常、クライアント呼び出しを実際のトピックに渡す前または後に、単純に呼び出しを実際のトピックオブジェクトに渡すのではなく、アクションを実行します.
3、リアルテーマロール:エージェントロールが表すリアルオブジェクトを定義します.

//      
			public abstract class Subject{
				public abstract void request();
			}
			
			//      
			public class RealSubject extends Subject{
				public RealSubject(){}
				
				public void request(){
					System.out.println("From real subject.");
				}
			}
			
			//      
			public class ProxySubject extends Subject{
				private RealSubject realSubject;
				
				public ProxySubject(){}
				
				public void request(){
					preRequest();
					if(realSubject == null){
						realSubject = new RealSubject();
					}
					realSubject.request();
					postRequest();
				}
				
				private void preRequest(){
					//..................
				}
				
				private void postRequest(){
					//....................
				}
			}
			
			//VectorProxy
			import java.lang.reflect.InvocationHandler;
			import java.lang.reflect.Proxy;
			import java.lang.reflect.Method;
			import java.util.Vector;
			import java.util.List;
			
			public class VectorProxy implements InvocationHandler{
				private Object proxyobj;
				
				public VectorProxy(Object obj){
					proxyobj = obj;
				}
				
				//      
				public static Object factory(Object obj){
					Class cls = obj.getClass();
					return cls.getClassLoader();
					cls.getInterface(new VectoryProxy(obj));
				}
				
				public Object invoke(Object proxy, Method method, Object[] args)throws Throwable{
					System.out.println("before calling" + method);
					if(args != null){
						for(int i = 0; i < args.length; i ++){
							System.out.println(args[i] + " ");
						}
					}
					Object o = method.invoke(proxyobj,args);
					System.out.println("after calling" + method);
					return o;
				}
				
				public static void main(String args[]){
					List v = null;
					v = (List)factory(new Vector(10));
					v.add("New");
					v.add("York");
				}
			}
			

三、代理モードのメリットとデメリット
1、メリット
1-リモートエージェント)利点は、クライアントがネットワークの存在を考慮する必要がないように、システムがネットワークの詳細を非表示にできることです.
お客様は、エージェントのオブジェクトがリモートではなくローカルドメインであり、エージェントがネットワーク通信の大部分を担当していると完全に考えられます.
 
2-仮想エージェント)エージェントは、必要に応じてエージェントのオブジェクトをロードできるという利点があります.
エージェントは、ロードされたプロセスを必要とする最適化を行うことができます.1つのモジュールのロードにリソースがかかる場合、仮想エージェントの利点は明らかです.
3-エージェントの保護)利点は、実行時間にユーザーの関連権限をチェックし、確認後に呼び出されたオブジェクトをエージェントに渡すことを決定できることです.
4-インテリジェントリファレンスエージェント)オブジェクトにアクセスするときに、いくつかの内務処理を実行できます.

//    
	//         :
		1、         
		2、      AccessValidator  ,             
		3、      RealSearcher  ,      
		4、      UsageLogger  ,      
		5、     RealSearcher             。
	//   
	public class Client{
		//         Searcher     
		private static Searcher searcher;
		
		public static void main(String args[]){
			//           Proxy
			searcher = new Proxy();
			String userId = "Admin";
			String searchType = "SEARCH_BY_ACCOUNT_NUMBER";
			String result = searcher.doSearch(userId,searchType);
			System.out.println(result);
		}
	}
	
	//      
	public interface Searcher{
		String doSearch(String userId,String searchType);
	}
	
	//    
	public class Proxy implements Searcher{
		private RealSearcher searcher;
		private UsageLogger usageLogger;
		private AccessValidator accessValidator;
		
		public Proxy(){
			searcher = new RealSearcher(); 
		}
		
		public String doSearch(String userId, String keyValue){
			if(checkAccess(userId)){
				String result = searcher.doSearch(null,keyValue);
				logUsage(userId);
				return result;
			}else{
				return null;
			}
		}
		
		public boolean checkAccess(String userId){
			accessValidator = new AccessValidator();
			return accessValidator.validateUser(userId);
		}
		
		private void logUsage(String userId){
			UsageLogger logger = new UsageLogger();
			logger.setUserId(userId);
			logger.save();
		}
	}
	
	//    
	public class RealSearcher implements Searcher{
		public RealSearcher(){}
		
		//            
		public String doSearch(String userId,String keyValue){
			String sql = "select * from data_table where key_col = '" + keyValue + "'";
			//execute SQL Statement
			//concatenate a result String
			return "result set";
		}
	}
	
	//       
	public class AccessValidator{
		//         
		public boolean validatorUser(String userId){
			if(userId.equals("Admin")){
				return true;
			}else{
				false;
			}
		}
	}
	
	//    
	public class UsageLogger{
		private String userId;
		
		public void setUserId(String userId){
			this.userId = userId;
		}
		
		public void save(){
			String sql = "insert into usage_table(user_id)" + "values(" + userId + ")";
			//execute sql
		}
		
		public void save(*String userId){
			this.userId = userId;
			save();
		}
	}