2009-03-05 2 views
4

Учитывая следующий код:Абстрактный базовый класс или интерфейс? Ни кажется правильным

using System.Collections.Generic; 
static class Program { 
    static void Main() { 
     bar Bar = new bar(); 
     baz Baz = new baz(); 
     System.Console.WriteLine(
      "We have {0} bars, rejoice!", bar.Cache.Count); 
    } 
} 

public abstract class foo { 
    public static List<foo> Cache = new List<foo>(); 
} 

public class bar : foo { 
    public bar() { Cache.Add(this); } 
} 
public class baz : foo { 
    public baz() { Cache.Add(this); } 
} 

Вы получаете (несколько ожидаемый) выход «У нас есть 2 бара, радуйтесь!».

Это потрясающе, теперь у нас есть в два раза больше мест для пива (по-видимому), но я действительно хочу, чтобы каждый класс имел свой собственный кеш. Причина, по которой я не хочу просто реализовывать этот кеш в подклассе, - это то, что у меня также есть некоторые методы в моем абстрактном классе, которые должны быть в состоянии работать в кеше (а именно, итерации по всем им). Есть ли способ сделать это? Я рассмотрел использование интерфейса для foo, но интерфейс не позволяет статическим членам быть определенными как часть интерфейса.

ответ

8

Каждый производный класс foo должен определять, как/где получить кеш, поэтому каждый может (потенциально) иметь свой собственный кеш. Методы в foo могут ссылаться на GetCache(), не будучи известными при реализации.

public abstract class foo 
{ 
    public abstract ICache GetCache(); 

    public void DoSomethingToCache() 
    { 
     ICache cache = this.GetCache(); 
     cache.DoSomething(); 
    } 
} 

public class bar : foo 
{ 
    public static ICache BarCache = new FooCache(); 

    public override ICache GetCache() 
    { 
     return bar.BarCache; 
    } 
} 

public class FooCache : ICache { } 
+0

Хорошо, что у нас есть функция «загрузить новые ответы». Я собирался опубликовать это. – moffdub

+0

ICache является интерфейсом к типу общего кэша? На самом деле, вы правы, мне нравится это лучше, хотя ответ thinkcube был ближе к тому, что я изначально искал. Это еще одна работа над дизайном для меня сейчас, хотя:) –

+1

Я не согласен, что это лучше. Теперь каждый подкласс должен беспокоиться о предоставлении собственного синглтона. Больше возможностей для дублирования кода. Вместо этого вы все равно можете использовать generics для получения одного класса singleton и выставлять его один раз с помощью GetCache(), но каждый подкласс не вынужден его реализовать. –

0

Вот ваш ответ:

using System; 
using System.Collections.Generic; 
static class Program 
{ 
    static void Main() 
    { 
     var bar = new Bar(); 
     var baz = new Baz(); 
     System.Console.WriteLine(
       "We have {0} bars, rejoice!", Bar.Cache.Count); 

     bar.PrintList(); 
     baz.PrintList(); 
    } 
} 

public abstract class Foo<T> 
{ 
    public static List<T> Cache = new List<T>(); 

    public void PrintList() 
    { 
     foreach(var item in Cache) 
     { 
      Console.WriteLine(item); 

     } 
    } 
} 

public class Bar : Foo<Bar> 
{ 
    public Bar() { Cache.Add(this); } 
} 
public class Baz : Foo<Baz> 
{ 
    public Baz() { Cache.Add(this); } 
} 
+0

Это кеш всех объектов этого типа. Как это работает, если оно не статично? –

+0

«но я действительно хочу, чтобы каждый класс имел свой собственный кеш». Вы либо делаете, либо нет. Выбери один. –

+0

Каждый класс, а не каждый экземпляр. –

-1

попробовать это:

using System.Collections.Generic; 
using System; 
static class Program 
{ 
    static void Main() 
    { 
    Bar bar = new Bar(); 
    Baz baz = new Baz(); 
    System.Console.WriteLine(
      "We have {0} bars, rejoice!", bar.Cache.Count); 
    System.Console.ReadKey(); 
    } 
} 

public abstract class Foo 
{ 
    public Foo() 
    { 
    Cache = new List<string>(); 
    } 
    public List<String> Cache { get; set; } 
} 

public class Bar : Foo 
{ 
    public Bar() 
    { 
    Cache.Add("Bar"); 
    } 
} 
public class Baz : Foo 
{ 
    public Baz() { Cache.Add("Baz"); } 
} 

К сожалению, я должен был изменить корпус .. Это делает моя голова взорвется

1
public abstract class foo { 
    public abstract List<foo> Cache { get; } 

    protected static Dictionary<Type, List<foo>> InnerCache = new Dictionary<Type, List<foo>>(); 
} 

public class bar : foo { 
    public override List<foo> Cache { 
     get { return foo.InnerCache[typeof(bar)]; } 
    } 

    public bar() { Cache.Add(this); } 
} 

public class baz : foo { 
    public override List<foo> Cache { 
     get { return foo.InnerCache[typeof(baz)]; } 
    } 

    public baz() { Cache.Add(this); } 
} 
+0

Арг, избил меня. Моя точная идея. – strager

4

Использовать общий базовый класс, параметризованный подклассом:

using System.Collections; 
using System.Collections.Generic; 

static class Program 
{ 
    static void Main() 
    { 
     bar Bar = new bar(); 
     baz Baz = new baz(); 
     System.Console.WriteLine(
       "We have {0} bars, rejoice!", Bar.GetCache().Count); 
    } 
} 

public abstract class foo<T> 
{ 
    private static List<foo<T> > Cache = new List<foo<T> >(); 

    public IList GetCache() 
    { 
     return Cache; 
    } 
} 

public class bar : foo<bar> 
{ 
    public bar() { GetCache().Add(this); } 
} 
public class baz : foo<baz> 
{ 
    public baz() { GetCache().Add(this); } 
} 
+0

Очень приятно, спасибо! –

+0

Ба, избили меня на 6 минут. Хорошее шоу. –

+0

Для записи, вероятно, должно быть: public abstract class foo где T: foo