1. 程式人生 > >設計模式學習筆記-代理模式

設計模式學習筆記-代理模式

定義:代理模式,為其他物件提供一種代理以控制對這個物件的訪問,及通過代理物件訪問目標物件,這樣可以在不修改原目標物件的前提下,提供額外的功能操作

應用場景:1、比如在某物件執行方法後,記錄日誌;

代理模式可以分為靜態代理和動態代理。靜態代理就是在程式碼編譯時,硬編碼到程式中的代理類;動態代理就是在程式執行是動態建立代理類。

靜態代理

這種代理方式需要目標物件和代理物件實現同樣的介面。

使用者管理的代理實現:

介面類:IUser

public interface IUser
{
    void AddUser(string name);
}

目標類:User

public
class User : IUser { public void AddUser(string name) { Console.WriteLine("新增使用者:{0}",name); } }

代理類:UserProxy

public class UserProxy : IUser
{
    private IUser User;
    public UserProxy(IUser _user)
    {
        User = _user;
    }
    public void AddUser(string name)
    {
        Console.WriteLine(
"新增使用者前做些什麼"); User.AddUser(name); Console.WriteLine("新增使用者後做些什麼"); } }

測試:

 UserProxy userProxy = new UserProxy(new User());
 userProxy.AddUser("Alan"); 
 Console.Read();

 輸出結果:

新增使用者前做些什麼
新增使用者:Alan
新增使用者後做些什麼

優點:

1、可以在不修改原有物件的前提下擴充套件目標物件的功能。

缺點:

1、冗餘,由於代理物件要與目標物件一致的介面,所以如果多個型別物件需要實現同樣的代理邏輯就需要擴充套件更多的代理類。

2、不易維護,如果介面增加了方法,那麼目標物件和代理物件都需要修改。

針對這些缺點,我們來學習一下動態代理。

動態代理

在C#中我們可以使用Castle.DynamicProxy動態的在記憶體中建立代理物件,從而實現對目標物件的代理功能。

接下來我們在原有介面的基礎上增加一個DeleteUser的方法,並且定義一個類UserIntercept實現IIntercept介面,程式碼如下:

注意要被代理的方法必須是virtual虛方法,因為它會被代理類重寫(override)

目標類:User

public class User : IUser
{
    public virtual void AddUser(string name)
    {
        Console.WriteLine("新增使用者:{0}", name);
    }

    public virtual void DeleteUser(string name)
    {
        Console.WriteLine("刪除使用者:{0}", name);
    }
}

攔截器類:UserIntercept

public class UserIntercept : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("操作使用者前");
        //執行代理方法
        invocation.Proceed();
        Console.WriteLine("操作使用者後");
    }
}

客戶端呼叫:

var proxyGenerator = new ProxyGenerator();
var handler = new UserIntercept();
IUser user = proxyGenerator.CreateClassProxy<User>(handler);
user.AddUser("Alan");

輸出結果:

操作使用者前
新增使用者:Alan
操作使用者後

 從以上結果中可以看出,動態代理就是彌補了靜態代理存在的缺陷,不管是代理多個不同型別的物件還是多個不同的方法都可以通過動態代理來擴充套件方法。