2013-04-18 1 views
1

Ok вопрос название далеко не о себе. Я вижу себя это часто делают:Общий базовый класс обертывает вложенный общий класс, чтобы уменьшить спецификацию аргумента типа: есть ли имя для этого шаблона?

От this answer:

public static class Equality<T> 
{ 
    public static IEqualityComparer<T> CreateComparer<K>(Func<T, K> keySelector) 
    { 
     return new KeyEqualityComparer<K>(keySelector); 
    } 



    class KeyEqualityComparer<K> : IEqualityComparer<T> 
    { 
     readonly Func<T, K> keySelector; 

     public KeyEqualityComparer(Func<T, K> keySelector) 
     {  
      this.keySelector = keySelector; 
     } 

     public bool Equals(T x, T y) 
     { 
      ---- 
     } 

     public int GetHashCode(T obj) 
     { 
      .... 
     } 
    } 
} 

Что я сделал: Существует деталь реализации KeyEqualityComparer<T, K>, которую я должен был назвать:

new KeyEqualityComparer<Person, int>(p => p.ID); 

К гнездованию это как частный класс, я не только скрыл реализацию (публичный конструктор внутреннего класса сейчас неясен), но получил более сильный синтаксис:

Equality<Person>.CreateComparer(p => p.ID); 

Обратите внимание, что я не унаследовал вложенный класс из родительского класса (который является статическим).

Или иногда я вижу себя doing this:

public abstract class Equater<T> : IEqualityComparer<T> 
{ 
    public static Equater<T> Create<TKey>(Func<T, TKey> keySelector) 
    { 
     return new Impl<TKey>(keySelector); 
    } 

    public abstract bool Equals(T x, T y); 

    public abstract int GetHashCode(T obj); 



    class Impl<TKey> : Equater<T> 
    { 
     readonly Func<T, TKey> keySelector; 

     public Impl(Func<T, TKey> keySelector) 
     { 
      this.keySelector = keySelector; 
     } 

     public override bool Equals(T x, T y) 
     { 
      ---- 
     } 

     public override int GetHashCode(T obj) 
     { 
      .... 
     } 
    } 
} 

Другой подобный один here

public class Accessor<S> 
{ 
    public static Accessor<S, T> Create<T>(Expression<Func<S, T>> memberSelector) 
    { 
     return new GetterSetter<T>(memberSelector); 
    } 

    class GetterSetter<T> : Accessor<S, T> 
    { 
     public GetterSetter(Expression<Func<S, T>> memberSelector) : base(memberSelector) 
     { 

     } 
    } 
} 

public class Accessor<S, T> : Accessor<S> 
{ 
    Func<S, T> Getter; 
    Action<S, T> Setter; 

    public bool IsReadable { get; private set; } 
    public bool IsWritable { get; private set; } 
    public T this[S instance] 
    { 
     get 
     { 
      if (!IsReadable) 
       throw new ArgumentException("Property get method not found."); 

      return Getter(instance); 
     } 
     set 
     { 
      if (!IsWritable) 
       throw new ArgumentException("Property set method not found."); 

      Setter(instance, value); 
     } 
    } 

    protected Accessor(Expression<Func<S, T>> memberSelector) //access not given to outside world 
    { 
     ---- 
    } 

} 

Обратите внимание, что в этих двух случаях я унаследованный от упаковки класса. Так что теперь я не только получить выгоды от первого, но я также могу поддерживать список, как это:

List<Equater<Person>> { persons with different implementations }; 

Его помогает мне время от времени. Итак, мне любопытно узнать, есть ли название для этого шаблона?

ответ

0

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

Я бы сказал, что, делегируя экземпляр конкретной реализации до CreateComparer, я просто упростил создание объекта, который находится под Creation Method patterns. Имея статическую функцию для создания объекта, это был своего рода заводской шаблон - в частности this variant of Factory Method.

Наследуя Impl от Equater я вроде следовал Abstract Factory модели - где Equater является завод завода и Impl является его реализация, чтобы дать Impl себя обратно, за исключением того, Impl действительно не создает каких-либо другого объекта (другими словами Impl не должен быть фабрикой), но получает экземпляр самостоятельно через конструктор. Таким образом, в строгом смысле это не шаблон абстрактной фабрики, но он будет ближе к тому, если Impl может иметь метод вызова самого конструктора и возврата экземпляра.

Также, встраивая и скрывая детали реализации (вложенные классы как таковые), открытый класс (родительский класс) подделывает внешний мир, как если бы он выполнял свою работу. Это то, что называется Delegation Pattern

Что касается названия для реализации тайника родового класса вложенного универсального класса, чтобы дать более простую подпись для вызовов метода обеспокоен я не думаю, что существует один. Даже если какое-либо имя существует, оно должно быть очень специфичным для языка (или подобных языков), поскольку задействованы языковые конструкции, такие как дженерики/тип и т. Д. Эрик Липперт находит такое же применение во вложенных классах here, хотя это не связано с дженериками, где он называет его Factory pattern.

1

Я не думаю, что вы следовали за каким-либо одним шаблоном здесь.

Я бы сказал, что, заменив несколько методов «CreateComparer» одним методом «Создать», вы просто упростили шаблон метода создания. Вы могли бы в некотором смысле сказать, что это была своего рода фабричная модель ?! Или, может быть, шаблон Builder - тот, который открыт для интерпретации, я думаю ?!

Встраивая «Impl» в «Equater», у вас есть вид следования за шаблоном Command - инкапсуляция вызова метода, так что ваш код вызова не знает о , как это делается.

В любом случае, извините, я не могу быть более полезным, чем это, или дать вам определенный ответ! В любом случае, надеюсь, что это поможет!

+0

Извините, я отредактировал ответ, так как я думаю, что я вообще не использовал шаблон команды или строителя. Не стесняйтесь редактировать, если есть расхождения в моем ответе – nawfal

+0

@nawfal: Хотя мы рекомендуем редактировать ответы, чтобы улучшить их, помните, что при этом вы должны уважать авторское авторское письмо. Ваше редактирование, по-видимому, слишком сильно изменилось в оригинальном ответе Берти - в частности, ваше редактирование в последнем абзаце потенциально может возникнуть, если положить слова в чужой рот. Тем не менее, я оставлю его Берти, чтобы решить, хочет ли он сохранить изменения или отбросить их обратно, поскольку ответ принадлежит ему. Если он отбросит их назад, вы можете опубликовать свое исследование в качестве своего собственного ответа. – BoltClock

+0

Спасибо BoltClock - я отбросил изменения, так как считаю, что слишком сильно изменил мой оригинальный ответ. Однако, если @nawfal предложит добавить свои комментарии в качестве нового ответа, то, очевидно, у меня нет проблем с этим. – Bertie