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();
    }
}