24 октября 2008 г.

Использование паттернов Strategy и Registry

Слишком много получилось писать в комментарии, решил вынести в отдельный пост.

В приведеном случае, когда логика постоянно меняется (пример кода в моем комментарии на пост Евгения), действительно лучше всего подойдет паттерн Visitor.

Но для такого простого варианта, когда классу ClassA соответствует определеная функция, лучше все-таки использовать Стратегию.

Предлагаю модификацию реализации стратегии Евгения.

Лучше вынести информацию о сопоставлении типа класса к IHandler в отдельную сущность. Т.е. создать статический Регистр с тем же словарем.

   1:  public class BaseClass
   2:  {
   3:  }
   4:   
   5:  public class ClassA : BaseClass
   6:  {
   7:  }
   8:   
   9:  public interface IHandler<T> where T : BaseClass
  10:  {
  11:      void DoFor(T obj);
  12:  }
  13:   
  14:  public class MyClass
  15:  {
  16:      public void DoSomethingWith<T>(T obj) where T : BaseClass
  17:      {
  18:          // какая-то логика
  19:   
  20:          HanlderRegistry.Get<T>().DoFor(obj);
  21:      }
  22:  }
  23:   
  24:  public static class HanlderRegistry
  25:  {
  26:      private static readonly Dictionary<Type, Type> _handlers = InitHanlders();
  27:   
  28:      private static Dictionary<Type, Type> InitHanlders()
  29:      {
  30:          return new Dictionary<Type, Type>
  31:          {
  32:              {typeof (ClassA), typeof(HanlderForClassA)}
  33:          };
  34:      }
  35:   
  36:      public static IHandler<T> Get<T>() where T : BaseClass
  37:      {
  38:          Type hanlderType = _handlers[typeof (T)];
  39:          return Activator.CreateInstance(hanlderType) as IHandler<T>;
  40:      }
  41:  }
  42:   
  43:  internal class HanlderForClassA : IHandler<ClassA>
  44:  {
  45:      #region Implementation of IHandler
  46:   
  47:      public void DoFor(ClassA obj)
  48:      {
  49:          // логика работы с классом ClassA
  50:      }
  51:   
  52:      #endregion
  53:  }

Здесь, HanlderRegistry - это единственное место, в котором происходит сопоставление обработчиков и подклассов BaseClass.

Естественно, пример очень абстрасктный, но думаю, что основную логику рефакторинга он показывает.

Если приводить пример более приближенный к реальности, то таким образом можно связать объект и его маппер в базу данных.

Комментариев нет:

Отправить комментарий