C# 对象缓存设计模式
我想知道是否有一种不那么痛苦的方式来写以下内容:C# 对象缓存设计模式,c#,caching,design-patterns,C#,Caching,Design Patterns,我想知道是否有一种不那么痛苦的方式来写以下内容: public class Company { // CEO, Programmer, and Janitor all inherit from an Employee class. private CEO _CacheCEO {get;} = CEOFactory.NewCEO(); private Programmer _CacheJavaProgrammer {get;} = ProgrammerFactory.NewJavaPr
public class Company {
// CEO, Programmer, and Janitor all inherit from an Employee class.
private CEO _CacheCEO {get;} = CEOFactory.NewCEO();
private Programmer _CacheJavaProgrammer {get;} = ProgrammerFactory.NewJavaProgrammer();
private Programmer _CacheIOSProgrammer {get;} = ProgrammerFactory.NewIOSProgrammer();
private Janitor _CacheJanitor {get;} = JanitorFactory.NewJanitor();
// etc.
public IEnumerable<Employee> GetEmployeesPresentToday() {
List<Employee> r = new List<Employee>();
if (ExternalCondition1) { // value of the condition may differ on successive calls to this method
r.Add(this._CacheCEO);
};
if (ExternalCondition2) { // all conditions are external to the Company class, and it does not get notified of changes.
r.Add(this._CacheJavaProgrammer);
}
if (ExternalCondition3) {
r.Add(this._CacheIOSProgrammer);
}
if (ExternalCondition4) {
r.Add(this._CacheJanitor);
}
// etc.
return r;
}
上市公司{
//CEO、程序员和看门人都继承自Employee类。
私有CEO_CacheCEO{get;}=CEOFactory.NewCEO();
私有程序员_CacheJavaProgrammer{get;}=ProgrammerFactory.NewJavaProgrammer();
私有程序员_CacheIOSProgrammer{get;}=ProgrammerFactory.NewIOSProgrammer();
私有看门人_cache门人{get;}=看门人工厂。新看门人();
//等等。
public IEnumerable GetEmployeesPresentToday(){
列表r=新列表();
if(ExternalCondition1){//连续调用此方法时,条件的值可能不同
r、 加上(本);
};
if(ExternalCondition2){//所有条件都是Company类的外部条件,并且不会收到更改通知。
r、 添加(此._CacheJavaProgrammer);
}
如果(外部条件3){
r、 添加(本程序);
}
如果(外部条件4){
r、 加上(这个._看门人);
}
//等等。
返回r;
}
让我头疼的是所有的私人ivar。如果我有(比如)30名不同的员工,那就很麻烦了。有没有办法避免每个员工都有一个单独的ivar
除了通过GetEmployeesPresentToday()方法之外,我可能不需要访问employee对象。换句话说,我不希望有任何代码询问“谁是您的CEO?”之类的问题
但是,重要的是,如果对GetEmployeesPresentToday()进行了两次不同的调用,并且上述代码中的Condition1每次都为true,那么相同的CEO对象应该出现在每个列表中。这里有一个可能的答案。但是,我不确定它是否比问题中的代码好
public class Company {
private Dictionary<string, Employee> _CacheEmployees { get;} = new Dictionary<string, Employee>();
public Employee GetEmployee(string key, Func<Employee> factory) {
// Existence of this method is not really annoying as it only has to be written once.
private Dictionary<string, Employee> cache = this._CacheEmployees;
Employee r = null;
if (cache.ContainsKey(key)) {
r = cache[key];
}
if (r == null) {
r = factory();
cache[key] = r;
}
return r;
}
public IEnumerable<Employee> GetEmployeesPresentToday() {
// still somewhat messy, but perhaps better than the question code.
List<Employee> r = new List<Employee>();
if (ExternalCondition1) { // value of the condition may differ on successive calls to this method
r.Add(this.GetEmployee("CEO", CEOFactory.NewCEO));
};
if (ExternalCondition2) { // all conditions are external to the Company class, and it does not get notified of changes.
r.Add(this.GetEmployee("Java Programmer", ProgrammerFactory.NewJavaProgrammer));
}
if (ExternalCondition3) {
r.Add(this.GetEmployee("IOS Programmer", ProgrammerFactory.NewIOSProgrammer));
}
if (ExternalCondition4) {
r.Add(this.GetEmployee("Janitor", JanitorFactory.NewJanitor));
}
// etc.
return r;
}
}
上市公司{
私有字典_CacheEmployees{get;}=new Dictionary();
公共雇员GetEmployee(字符串键,Func工厂){
//这个方法的存在并不是很烦人,因为它只需要编写一次。
私有字典缓存=此。\u CacheEmployees;
员工r=null;
if(cache.ContainsKey(键)){
r=缓存[键];
}
if(r==null){
r=工厂();
cache[key]=r;
}
返回r;
}
public IEnumerable GetEmployeesPresentToday(){
//仍然有些混乱,但可能比问题代码更好。
列表r=新列表();
if(ExternalCondition1){//连续调用此方法时,条件的值可能不同
r、 添加(this.GetEmployee(“CEO”,CEOFactory.NewCEO));
};
if(ExternalCondition2){//所有条件都是Company类的外部条件,并且不会收到更改通知。
r、 添加(this.GetEmployee(“Java程序员”,ProgrammerFactory.NewJavaProgrammer));
}
如果(外部条件3){
r、 添加(this.GetEmployee(“IOS程序员”,ProgrammerFactory.NewIOS程序员));
}
如果(外部条件4){
r、 添加(this.GetEmployee(“看门人”,看门人工厂,新看门人));
}
//等等。
返回r;
}
}
我很想使用惰性
和字典
来实现完全惰性的实现,例如:
public sealed class Company
{
private readonly Dictionary<string, Lazy<Employee>> _cache = new Dictionary<string, Lazy<Employee>>();
public Company()
{
_cache["CEO"] = new Lazy<Employee>(CeoFactory.NewCeo);
_cache["Janitor"] = new Lazy<Employee>(JanitorFactory.NewJanitor);
_cache["IosProgrammer"] = new Lazy<Employee>(ProgrammerFactory.NewIosProgrammer);
_cache["JavaProgrammer"] = new Lazy<Employee>(ProgrammerFactory.NewJavaProgrammer);
}
public IEnumerable<Employee> GetEmployeesPresentToday(bool cond1, bool cond2, bool cond3, bool cond4)
{
if (cond1)
yield return _cache["CEO"].Value;
if (cond2)
yield return _cache["JavaProgrammer"].Value;
if (cond3)
yield return _cache["IosProgrammer"].Value;
if (cond4)
yield return _cache["Janitor"].Value;
}
或者,您可以通过传入一个谓词
,使条件检查的实现不暴露于GetEmployeesPresentToday()
:
字典中的类型到对象映射,而不是每个员工类型的变量?给定类型的员工可能不止一个;我对问题进行了编辑,以澄清这一点。如果你能给它一个不同的变量名,那对我来说是不同的类型。我不是指类等上下文中的类型。对,字符串键控字典或诸如此类。这是一个答案,但我不确定它是否是最好的。我会把它写下来,看看是否有人能做得更好。要得到更好的答案,你的例子可能有点抽象。对我来说,类看起来是不变的,我们对条件没有概念。它们如何变化?
public IEnumerable<Employee> GetEmployeesPresentToday(Dictionary<string, bool> want)
{
if (want["CEO"])
yield return _cache["CEO"].Value;
if (want["JavaProgrammer"])
yield return _cache["JavaProgrammer"].Value;
if (want["IosProgrammer"])
yield return _cache["IosProgrammer"].Value;
if (want["Janitor"])
yield return _cache["Janitor"].Value;
}
public IEnumerable<Employee> GetEmployeesPresentToday(Predicate<string> want)
{
if (want("CEO"))
yield return _cache["CEO"].Value;
if (want("JavaProgrammer"))
yield return _cache["JavaProgrammer"].Value;
if (want("IosProgrammer"))
yield return _cache["IosProgrammer"].Value;
if (want("Janitor"))
yield return _cache["Janitor"].Value;
}
public abstract class Employee
{
}
public sealed class Ceo: Employee
{
}
public abstract class Programmer: Employee
{
}
public sealed class JavaProgrammer: Programmer
{
}
public sealed class IosProgrammer: Programmer
{
}
public sealed class Janitor: Employee
{
}
public static class ProgrammerFactory
{
public static Programmer NewJavaProgrammer()
{
return new JavaProgrammer();
}
public static Programmer NewIosProgrammer()
{
return new IosProgrammer();
}
}
public static class CeoFactory
{
public static Ceo NewCeo()
{
return new Ceo();
}
}
public static class JanitorFactory
{
public static Janitor NewJanitor()
{
return new Janitor();
}
}