|
在有些情況下,一個(gè)客戶不能或者不想直接訪問另一個(gè)對(duì)象,這時(shí)需要找一個(gè)中介幫忙完成某項(xiàng)任務(wù),這個(gè)中介就是代理對(duì)象。 定義與特點(diǎn)由于某些原因需要給某對(duì)象提供一個(gè)代理以控制對(duì)該對(duì)象的訪問。這時(shí),訪問對(duì)象不適合或者不能直接引用目標(biāo)對(duì)象,代理對(duì)象作為訪問對(duì)象和目標(biāo)對(duì)象之間的中介。 主要優(yōu)點(diǎn)有:
主要缺點(diǎn)有:
結(jié)構(gòu)與實(shí)現(xiàn)代理模式的結(jié)構(gòu)比較簡單,主要是通過定義一個(gè)繼承抽象主題的代理來包含真實(shí)主題,從而實(shí)現(xiàn)對(duì)真實(shí)主題的訪問。 模式的結(jié)構(gòu)代理模式的主要角色如下:
其結(jié)構(gòu)圖如圖所示:
模式的實(shí)現(xiàn)代理模式的實(shí)現(xiàn)代碼如下: //訪問類
class Program
{
static void Main(string[] args)
{
//代理模式
Proxy proxy=new Proxy();
proxy.Request();
Console.ReadKey();
}
}
//抽象主題
public interface ISubject
{
void Request();
}
//真實(shí)主題
public class RealSubject :ISubject
{
public void Request()
{
Console.WriteLine("訪問真實(shí)主題方法...");
}
}
//代理
public class Proxy : ISubject
{
private RealSubject realSubject;
public void Request()
{
if (realSubject==null)
{
realSubject=new RealSubject();
}
PreRequest();
realSubject.Request();
PostRequest();
}
public void PreRequest()
{
Console.WriteLine("訪問真實(shí)主題之前的預(yù)處理。");
}
public void PostRequest()
{
Console.WriteLine("訪問真實(shí)主題之后的后續(xù)處理。");
}
}程序運(yùn)行的結(jié)果如下: 訪問真實(shí)主題之前的預(yù)處理。 訪問真實(shí)主題方法... 訪問真實(shí)主題之后的后續(xù)處理。 應(yīng)用場(chǎng)景前面分析了代理模式的結(jié)構(gòu)與特點(diǎn),現(xiàn)在來分析以下的應(yīng)用場(chǎng)景:
擴(kuò)展:動(dòng)態(tài)代理模式在前面介紹的代理模式中,代理類中包含了對(duì)真實(shí)主題的引用,這種方式存在兩個(gè)缺點(diǎn):
采用動(dòng)態(tài)代理模式可以解決以上問題(如 SpringAOP),C#中可以使用RealProxy實(shí)現(xiàn)動(dòng)態(tài)代理,有兩種方法: class Program
{
static void Main(string[] args)
{
Console.WriteLine("***\r\n Begin program - logging with decorator\r\n");
IRepository<Customer> customerRepository =RepositoryFactory.Create<Customer>();
var customer = new Customer()
{
Id = 1,
Name = "Customer 1",
Address = "Address 1"
};
customerRepository.Add(customer);
customerRepository.Update(customer);
customerRepository.Delete(customer);
Console.WriteLine("\r\nEnd program - logging with decorator\r\n***");
Console.ReadLine();
}
}
//客戶類
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
//存儲(chǔ)庫接口
public interface IRepository<T>
{
void Add(T entity);
void Delete(T entity);
void Update(T entity);
IEnumerable<T> GetAll();
T GetById(int id);
}
//真實(shí)儲(chǔ)存庫
public class Repository<T> : IRepository<T>
{
public void Add(T entity)
{
Console.WriteLine("Adding {0}", entity);
}
public void Delete(T entity)
{
Console.WriteLine("Deleting {0}", entity);
}
public void Update(T entity)
{
Console.WriteLine("Updating {0}", entity);
}
public IEnumerable<T> GetAll()
{
Console.WriteLine("Getting entities");
return null;
}
public T GetById(int id)
{
Console.WriteLine("Getting entity {0}", id);
return default(T);
}
}
//動(dòng)態(tài)代理
class DynamicProxy<T> : RealProxy
{
private readonly T _decorated;
public DynamicProxy(T decorated) : base(typeof(T))
{
_decorated = decorated;
}
private void Log(string msg, object arg = null)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(msg, arg);
Console.ResetColor();
}
public override IMessage Invoke(IMessage msg)
{
var methodCall = msg as IMethodCallMessage;
var methodInfo = methodCall.MethodBase as MethodInfo;
Log("In Dynamic Proxy - Before executing '{0}'",methodCall.MethodName);
try
{
var result = methodInfo.Invoke(_decorated, methodCall.InArgs);
Log("In Dynamic Proxy - After executing '{0}' ",methodCall.MethodName);
return new ReturnMessage(result, null, 0,methodCall.LogicalCallContext, methodCall);
}
catch (Exception e)
{
Log(string.Format("In Dynamic Proxy- Exception {0} executing '{1}'", e),methodCall.MethodName);
return new ReturnMessage(e, methodCall);
}
}
}
//存?zhèn)}庫過程,自動(dòng)執(zhí)行代理
public class RepositoryFactory
{
public static IRepository<T> Create<T>()
{
var repository = new Repository<T>();
var dynamicProxy = new DynamicProxy<IRepository<T>>(repository);
return dynamicProxy.GetTransparentProxy() as IRepository<T>;
}
}第二種:使用RealProxy、MarshalByRefObject,可以代理帶out參數(shù)的方法,代碼如下: //訪問類
public class Program
{
static void Main(string[] args)
{
//動(dòng)態(tài)代理模式
Proxy<ISubject> proxy = new Proxy<ISubject>(new RealSubject());
ISubject subject = (ISubject)proxy.GetTransparentProxy();
int arg = 0;
subject.Request(out arg);
Console.WriteLine(arg);
Console.ReadKey();
}
}
//代理類
public class Proxy<T> : RealProxy where T: class
{
MarshalByRefObject myMarshalByRefObject;
public Proxy(MarshalByRefObject realT) : base(typeof(T))
{
myMarshalByRefObject = realT;
}
public override IMessage Invoke(IMessage myMessage)
{
IMethodCallMessage myCallMessage = (IMethodCallMessage)myMessage;
Console.WriteLine("動(dòng)態(tài)代理方法中:執(zhí)行前");
IMethodReturnMessage myIMethodReturnMessage = RemotingServices.ExecuteMessage(myMarshalByRefObject, myCallMessage);
Console.WriteLine("動(dòng)態(tài)代理方法中:執(zhí)行后");
return myIMethodReturnMessage;
}
}
//抽象主題
public interface ISubject
{
void Request(out int arg);
}
//真實(shí)主題
public class RealSubject : MarshalByRefObject,ISubject
{
public void Request(out int arg)
{
arg = 1;
Console.WriteLine("訪問真實(shí)主題方法...");
}
}參考資料C#中動(dòng)態(tài)代理與泛型函數(shù)——CSDN |
|
|