裝飾者模式介紹
裝飾器模式(Decorator Pattern)是在不改變原類和使用繼承的情況下,動態地給一個對象添加一些額外的職責。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。
可以在如下使用場景中使用裝飾器模式:
在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。
需要動態地給一個對象增加功能,這些功能也可以動態地被撤銷。
當不能采用繼承的方式對系統進行擴充或者采用繼承不利于系統擴展和維護時。
Demo
假設,我們使用IRepository
接口的實現類Repository
進行數據庫訪問:
public?interface?IUserRepository
{User?Get(int?Id);
}public?class?UserRepository?:?IUserRepository
{public?User?Get(int?Id){Console.WriteLine("訪問數據庫");//模擬數據庫訪問return?new?User(Id,?"My?IO");}
}
現在有一個新的需求:要求增加緩存功能,即先從緩存獲取數據,緩存不存在再訪問數據庫。
有幾種方法可以做到這一點:
修改業務邏輯,在訪問
Get
前讀取緩存;使用面向切面(AOP)模式,在調用
Get
方法時注入讀取緩存邏輯;修改
UserRepository
實現緩存功能;繼承
UserRepository
類,在派生類中實現緩存功能;使用裝飾器模式封裝
UserRepository
類,在新的UserRepositoryDecorator
類中嵌入實現緩存功能;
在這里,我們使用裝飾器模式:
internal?class?UserRepositoryCacheDecorator?:?IUserRepository
{private?readonly?IUserRepository?_userRepository;public?UserRepositoryCacheDecorator(IUserRepository?userRepository){_userRepository?=?userRepository;}public?User?Get(int?Id){Console.WriteLine("訪問緩存");return?_userRepository.Get(Id);}
}
首先,我們還是實現與
UserRepository
類相同的IUserRepository
接口;其次,我們將
IUserRepository
接口注入到構造函數中;最后,在
Get
方法中,我們再次調用注入的接口的Get
方法,它應該調用UserRepository
類的實現。
顯然,如果還是按普通方式進行依賴注入,將不可能成功:
builder.Services.AddTransient<IUserRepository,?UserRepository>();builder.Services.AddTransient<IUserRepository,?UserRepositoryCacheDecorator>();
這時,我們可以引用 Nuget 包Scrutor
,然后使用它提供的Decorate
方法:
builder.Services.AddTransient<IUserRepository,?UserRepository>();builder.Services.Decorate<IUserRepository,?UserRepositoryCacheDecorator>();
現在再運行,你將看到裝飾器模式已經實現了:
結論
可以添加多個裝飾,為原來的功能增加不同的職責,而僅需的操作,就是調用Decorate
方法進行注冊:
builder.Services.Decorate<IUserRepository,?UserRepositoryCacheDecorator>();builder.Services.Decorate<IUserRepository,?UserRepositoryLogDecorator>();
添加微信號【MyIO666】,邀你加入技術交流群