Фабрика объектов с разными конструкторами
От: licedey  
Дата: 05.11.16 13:55
Оценка:
Есть интерфейс и несколько производных классов которые реализуют метод Validate. В довесок к нему, существует интерейс IPaymentProcessor,
которы применяет все правила, т.е. создает объект и вызвает метод Validate() у Rule1, Rule2, итд.
Задача: реализовать IPaymentProcessor
 public interface IBusinessRule
 {
        bool Validate();
 }

  class Rule1 : IBusinessRule
  {
      public Rule1(string name) { ... }
      bool Validate() { ... }
  }

  class Rule2 : IBusinessRule
  {
      public Rule1(int month, int year) { ... }
      bool Validate() { ... }
  }

  interface IPaymentProcessor
  {
    bool MakePayment(CreditCard card);
  }

  class MyPaymentProcess : IPaymentProcessor
  {
    public bool MakePayment(CreditCard card)
     {
        // Вот тут засада. Если нам нужно добавить/удбрать правило, меняется конструктор итд.,
        // То надо лезть в этот код. Что совсем не правильно.
        var rules = new List<IBusinessRule>() { new Rule1(card.Name), new Rule2(card.Month, card.Year) };  
        foreach(var r in rules) if(!r.Validate()) { return false; }
        return true;
    }
  }


Вопрос: как заменить создание списка на лету, какой-нибудь фабрикой или контейнером, чтобы уменьшить связность? Желательно из готовых решений под .NET, еще лучше через Ninject (так в требованиях).
Копая в сторону Ninject/DI, натыкался на проблему: либо непонятно как разное кол-во параметров в конструкторе,
либо непонятно в по какому принципу делать ninjectKernel.Get, или в нашем случае что-то вроде GetAll, для перечисления.
ninject фабрика
Re: Фабрика объектов с разными конструкторами
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 05.11.16 14:40
Оценка: +1
Здравствуйте, licedey, Вы писали:

L>Вопрос: как заменить создание списка на лету, какой-нибудь фабрикой или контейнером, чтобы уменьшить связность? Желательно из готовых решений под .NET, еще лучше через Ninject (так в требованиях).



У тебя список меняется во время работы программы?
Если нет просто положи его в статическую переменную. Если хочется модноты, то зарегистрируй все экземпляры в ioc-контейнере и вызывай getall.

Если да, то как устроен сериализатор? Может ли он создать экземпляр класса с параметрами?

Если у тебя конкретные правила зависят от контекста, то есть используют параметры доступные в конкретном запросе, то просто добавь уровень коссвенности. Сделай класс-билдер, который в конструкторе принимает фиксированные парамтеры, а в методе build — контекстные. И сохраняй список билдеров.
Re[2]: Фабрика объектов с разными конструкторами
От: licedey  
Дата: 05.11.16 15:07
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, licedey, Вы писали:


L>>Вопрос: как заменить создание списка на лету, какой-нибудь фабрикой или контейнером, чтобы уменьшить связность? Желательно из готовых решений под .NET, еще лучше через Ninject (так в требованиях).



G>У тебя список меняется во время работы программы?

G>Если нет просто положи его в статическую переменную. Если хочется модноты, то зарегистрируй все экземпляры в ioc-контейнере и вызывай getall.
В статическую не получится, потому что приходит куча запросов с разными CreditCard, а уже на основе этого объекта и создаются валидаторы.


G>Если да, то как устроен сериализатор? Может ли он создать экземпляр класса с параметрами?

Эмм...а зчем тут сериализатор, это бизес-логика ASP.NET MVC приложения. По Api прихоят данные о CreditCard, а задача класса PaymentProcessor
валидировать ее корректность и вернуть true/false

G>Если у тебя конкретные правила зависят от контекста, то есть используют параметры доступные в конкретном запросе, то просто добавь уровень коссвенности. Сделай класс-билдер, который в конструкторе принимает фиксированные парамтеры, а в методе build — контекстные. И сохраняй список билдеров.

Про билдер подумаю, пока сделал так, но в том же Ninject или AutoFixter, это как-то все моднее и на основе рефлексии.
Пока улушли решение через делегаты-creator'ы, которые лежат в списке, мы по нему пробегаем и делагаты создают каждый Instance. Но до сих пор кажется что велосипед.
Re: Фабрика объектов с разными конструкторами
От: velkin Удмуртия http://blogs.rsdn.org/effective/
Дата: 05.11.16 15:19
Оценка:
Здравствуйте, licedey, Вы писали:

L>Вопрос: как заменить создание списка на лету, какой-нибудь фабрикой или контейнером, чтобы уменьшить связность? Желательно из готовых решений под .NET, еще лучше через Ninject (так в требованиях).


Под .NET не знаю, но вот классика QMetaObject. Его мы можем получить с помощью const QMetaObject * QObject::metaObject() const. В QMetaObject есть метод newInstance, хотя это не особо принципиально даже если бы пришлось создавать фабричный метод, особенно учитывая, что большинство классов унаследованы от QObject.

QObject * newInstance(QGenericArgument val0 = QGenericArgument( 0 ), QGenericArgument val1 = QGenericArgument(), QGenericArgument val2 = QGenericArgument(), QGenericArgument val3 = QGenericArgument(), QGenericArgument val4 = QGenericArgument(), QGenericArgument val5 = QGenericArgument(), QGenericArgument val6 = QGenericArgument(), QGenericArgument val7 = QGenericArgument(), QGenericArgument val8 = QGenericArgument(), QGenericArgument val9 = QGenericArgument()) const

Важны на мой взгляд две вещи:
1) Первое это enumerators, то есть перечислители. Можно динамически получить название методов, а так же вызывать их, или там связать сигналы слоты. А можно работать со свойствами и так далее. Другое дело не стоит забывать, что всё это сделано на switch.
2) Второе это получение интерфейса и соответственно полиморфизм посредством виртуальных методов.

Всё это даёт возможность добавлять новые объекты из тех же плагинов и создавать новый функционал связывая их каким-либо способом. Ну, а что касается .NET, то на Qt я ушёл не только потому, что это кроссплатформа и C++, а ещё и потому, что Qt обладал теми же самыми возможностями, то есть интроспекцией. Если на Qt всё это протестировал лично с плагинами, то в те далёкие времена на .NET мне это как-то не довелось.

Можно, конечно, лепить типа того, что описано в "Приёмы объектно-ориентированного проектирования. Паттерны проектирования" Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидс. А можно воспользоваться и иными архитектурами, что нам и демонстрируют различные метаобъектные системы.
Re[3]: Фабрика объектов с разными конструкторами
От: Sinix  
Дата: 05.11.16 16:08
Оценка:
Здравствуйте, licedey, Вы писали:

G>>Если нет просто положи его в статическую переменную. Если хочется модноты, то зарегистрируй все экземпляры в ioc-контейнере и вызывай getall.

L>В статическую не получится, потому что приходит куча запросов с разными CreditCard, а уже на основе этого объекта и создаются валидаторы.

1. Разделить код на две части: классы с логикой обработки и подбор нужного класса.
2. Сделать удобное API для каждой из частей.
3. Спрятать за API реализацию. Стартовые два варианта: или добавляем в обработчик метод CanProcess(), или храним в настройках сопоставление "набор условий => обработчик". Дальше допиливается по обстановке.

L>Про билдер подумаю, пока сделал так, но в том же Ninject или AutoFixter, это как-то все моднее и на основе рефлексии.

Лучше сначала решить проблему, а уж затем с чистой совестью гоняться за шашечками. Меньше переписывать придётся.
Re: Фабрика объектов с разными конструкторами
От: antropolog  
Дата: 05.11.16 16:09
Оценка: +1
Здравствуйте, licedey, Вы писали:

вы лучше скажите, почему ваши абстрактные рулы принимают какие-то абстрактные имя, месяц, год. Если я правильно понял, они валидируют именно имя владельца карты, или месяц год окончания действия карты. Т.е. они же работают не с абстрактными "строка", "дата", а с вполне себе конкретными — с данными карты, и логика проверки знает о том, что это данные карты, а некакие-то абстрактные. Вот и передавайте туда карту целиком. Тогда ваш вопрос разрешится сам собой.
Re[2]: Фабрика объектов с разными конструкторами
От: licedey  
Дата: 05.11.16 18:11
Оценка:
Здравствуйте, velkin, Вы писали:

V>Здравствуйте, licedey, Вы писали:


L>>Вопрос: как заменить создание списка на лету, какой-нибудь фабрикой или контейнером, чтобы уменьшить связность? Желательно из готовых решений под .NET, еще лучше через Ninject (так в требованиях).


V>Под .NET не знаю, но вот классика QMetaObject. Его мы можем получить с помощью const QMetaObject * QObject::metaObject() const. В QMetaObject есть метод newInstance, хотя это не особо принципиально даже если бы пришлось создавать фабричный метод, особенно учитывая, что большинство классов унаследованы от QObject.

V>

V> QObject * newInstance(QGenericArgument val0 = QGenericArgument( 0 ), QGenericArgument val1 = QGenericArgument(), QGenericArgument val2 = QGenericArgument(), QGenericArgument val3 = QGenericArgument(), QGenericArgument val4 = QGenericArgument(), QGenericArgument val5 = QGenericArgument(), QGenericArgument val6 = QGenericArgument(), QGenericArgument val7 = QGenericArgument(), QGenericArgument val8 = QGenericArgument(), QGenericArgument val9 = QGenericArgument()) const


Признаться не понял как это работает указанный код на плюсах, но по описанию похоже на рефлексию в .NET. Возиться с ней только не хочется, сильно громоздкий код получается,
с кучей проверок. Поэтому пытаясь сделать решение наиболее лаконичным, пока остановился на делегатах, которые создают сущности с любыми конструкторама, возвращая инстансы наследников IRule.
А в идеальном мире, хотелось бы что-то вроде:
// Вот в этом месте, хотелось бы IRuleFactory на лету создать. Делается через Ninject/DI-паттерн
public PaymentProcessor(IRuleFactory factory)      
{
    // И тут что вроде такого билдера. Но это надо свой велосипед писать. В принципе его и написал уже.
    this._factory = factory.Build().Add<Rule1>(c => c.CardName).Add<Rule2>(c => c.Month, c => c.Year);    
}

public bool MakePayment(CreditCard c)
{
    return _factory.GetAll(c).All(v => v.Validate());    
}
Re[2]: Фабрика объектов с разными конструкторами
От: licedey  
Дата: 05.11.16 18:14
Оценка:
Здравствуйте, antropolog, Вы писали:

A>Здравствуйте, licedey, Вы писали:


A>вы лучше скажите, почему ваши абстрактные рулы принимают какие-то абстрактные имя, месяц, год. Если я правильно понял, они валидируют именно имя владельца карты, или месяц год окончания действия карты. Т.е. они же работают не с абстрактными "строка", "дата", а с вполне себе конкретными — с данными карты, и логика проверки знает о том, что это данные карты, а некакие-то абстрактные. Вот и передавайте туда карту целиком. Тогда ваш вопрос разрешится сам собой.


Мне на StackOverflow уже 10 человек об этом сказали . Но это тестовое задание (причем не мое), на знание DI, ООП, SOLID, Юнит-тестирования.
В приложении к нему такие классы прицепили, т.е. задача надуманная, а требование от меня — показать скиллы с выдподвыпертом.
Re[3]: Фабрика объектов с разными конструкторами
От: StatujaLeha на правах ИМХО
Дата: 05.11.16 19:18
Оценка:
Здравствуйте, licedey, Вы писали:

L>Мне на StackOverflow уже 10 человек об этом сказали . Но это тестовое задание (причем не мое), на знание DI, ООП, SOLID, Юнит-тестирования.

L>В приложении к нему такие классы прицепили, т.е. задача надуманная, а требование от меня — показать скиллы с выдподвыпертом.

Это новая форма поиска кандидатов:
1. Запостить чье-то ТЗ на форум в профильный раздел.
2. Попросить критику/подсказки/etc.
3. Понравившихся берем в оборот.

Я угадал?
Re[3]: Фабрика объектов с разными конструкторами
От: Sinix  
Дата: 05.11.16 20:38
Оценка: +1
Здравствуйте, licedey, Вы писали:

L>Мне на StackOverflow уже 10 человек об этом сказали . Но это тестовое задание (причем не мое), на знание DI, ООП, SOLID, Юнит-тестирования.

L>В приложении к нему такие классы прицепили, т.е. задача надуманная, а требование от меня — показать скиллы с выдподвыпертом.

А, собеседования, бессмысленные и беспощадные. Удачи!
Re[4]: Фабрика объектов с разными конструкторами
От: licedey  
Дата: 05.11.16 21:02
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

SL>Здравствуйте, licedey, Вы писали:


L>>Мне на StackOverflow уже 10 человек об этом сказали . Но это тестовое задание (причем не мое), на знание DI, ООП, SOLID, Юнит-тестирования.

L>>В приложении к нему такие классы прицепили, т.е. задача надуманная, а требование от меня — показать скиллы с выдподвыпертом.

SL>Я угадал?


Нет. Это фриланс, я исполнитель.
Re[4]: Фабрика объектов с разными конструкторами
От: licedey  
Дата: 05.11.16 21:03
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, licedey, Вы писали:


L>>Мне на StackOverflow уже 10 человек об этом сказали . Но это тестовое задание (причем не мое), на знание DI, ООП, SOLID, Юнит-тестирования.

L>>В приложении к нему такие классы прицепили, т.е. задача надуманная, а требование от меня — показать скиллы с выдподвыпертом.

S>А, собеседования, бессмысленные и беспощадные. Удачи!


Спасибо Передам французу ,которому этот код объяснить еще надо будет..
Re: Фабрика объектов с разными конструкторами
От: · Великобритания  
Дата: 07.11.16 11:28
Оценка:
Здравствуйте, licedey, Вы писали:

L>Задача: реализовать IPaymentProcessor

Я бы как-то так сделал:

 public interface IBusinessRule
 {
        bool Validate();
 }

 class Rule1 : IBusinessRule
 {
      public Rule1(string name) { ... }
      bool Validate() { ... }
 }

 class Rule2 : IBusinessRule
 {
      public Rule1(int month, int year) { ... }
      bool Validate() { ... }
 }

 class CompositeBusinessRule : IBusinessRule
 {
      const IBusinessRule rules;
      CompositeBusinessRule(IBusinessRule rules...) {this.rules = rules;}
      bool Validate() {
           foreach(var r in rules) if(!r.Validate()) { return false; }
           return true;
      }
 }

 interface IPaymentProcessor
 {
    bool MakePayment(CreditCard card);
 }

 class CreditCardValidatorFactory
 {
    IBusinessRule createValidation(CreditCard card)
        {
           return new CompositeBusinessRule(
                 new Rule1(card.Name),
                 new Rule2(card.Month, card.Year)
           );
        }
 }

 interface IPaymentProcessor
 {
    bool MakePayment(CreditCard card);
 }

 class MyPaymentProcess : IPaymentProcessor
 {
    const CreditCardValidatorFactory validatorFactory;
        MyPaymentProcess(CreditCardValidatorFactory validatorFactory) { this.validatorFactory = validatorFactory;}

    public bool MakePayment(CreditCard card)
     {
        IBusinessRule validator = validatorFactory.createValidation(card);
        if(!validator.Validate()) { return false; }
        return true;
    }
 }

А следующим шагом я бы изменил IBusinessRule чтобы они ещё репортили ошибку c подробностями что случилось, а не просто true/false.

ЗЫЖ Ninject — фтопку, как и все IoC-фреймворки.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 07.11.2016 11:32 · . Предыдущая версия .
Re[3]: Фабрика объектов с разными конструкторами
От: maxkar  
Дата: 07.11.16 12:37
Оценка:
Здравствуйте, licedey, Вы писали:

G>>У тебя список меняется во время работы программы?

G>>Если нет просто положи его в статическую переменную. Если хочется модноты, то зарегистрируй все экземпляры в ioc-контейнере и вызывай getall.
L>В статическую не получится, потому что приходит куча запросов с разными CreditCard, а уже на основе этого объекта и создаются валидаторы.

Не очень интерфейс у вашего валидатора. По интерфейсу "валидатор" является оберткой над Boolean (с точностью до момента вычисления). Естественно, с этим работать очень неудобно.

Это все прекрасно лечится исправлением интерфейса:

public interface Validator<T> {
  public boolean validate(T item);
}

public final class CompositeValidator<T> implements Validator<T> {
  private List<Validator<T>> peers;
  CompositeValidator(List<Validator<T>> peers) {
    this.peers = peers;
  }

  @Override
  public boolean validate(T item) {
    for (Validator<T> peer : peers)
      if (!peer.validate(item))
        return false;
    return true;
  }
}


public final class LegacyRule1Adapter implements Validator<CreditCard> {
  @Override
  public boolean validate(CreditCard item) {
    return new Rule1(item.Name).validate();
  }
}

public final class LegacyRule2Adapter implements Validator<CreditCard> {
  @Override
  public boolean validate(CreditCard item) {
    return new Rule2(item.Month, item.Year).validate();
  }
}


public final class MyPaymentProcessor {
  private final Validator<CreditCard> validator;
  MyPaymentProcessor(Validator<CreditCard> validator) {
    this.validator = validator;
  }

  @Override
  public boolean makePayment(CreditCard card) {
    if (!validator.validate(card))
      return false;
    return true;
  }
}

// Somewhere in the app startup/config/injection code:
final Validator<CreditCard> paymentCardValidator = new CompositeValidator<>(
  new LegacyRule1Adapter(), new LegacyRule2Adapter()
);
final PaymentProcessor = new MyPaymentProcessor(paymentCardValidator);


Legacy Adapter'ов в простейшем случае наделать для каждого правила. В более сложном можно посмотреть на какой-нибудь reflection на базе класса, реализующего IBusinessRule (например, принимающий тип аргумента, конструктор правила и имена полей для передачи в конструктор). Еще можно композитный процессор за статической фабрикой спрятать. Еще композицию можно развивать (conditional validators, etc...), все зависит от языка (нужна удобная поддержка лямбд (анонимных функций)).

В итоге — никаких лишних уровней абстракции вроде "фабрик возвращающих фабрики возвращающих фабрики".
Re[4]: Фабрика объектов с разными конструкторами
От: · Великобритания  
Дата: 07.11.16 12:55
Оценка: +1
Здравствуйте, maxkar, Вы писали:

M>Это все прекрасно лечится исправлением интерфейса:

M>
M>public interface Validator<T> {
M>

А мне так не нравится. На пустом месте использовать генерики.

M>посмотреть на какой-нибудь reflection на базе класса

И очередной рефлективный фреймворк-всемогутер.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[5]: Фабрика объектов с разными конструкторами
От: Sinix  
Дата: 07.11.16 13:11
Оценка: 1 (1) :))
Здравствуйте, ·, Вы писали:

·>И очередной рефлективный фреймворк-всемогутер.


Тут нюанс есть: клиент от топикстартера хочет шашечки, а не ехать. Так что предложение вполне в духе.
Re[2]: Фабрика объектов с разными конструкторами
От: licedey  
Дата: 08.11.16 08:43
Оценка:
Здравствуйте, ·, Вы писали:

·>Здравствуйте, licedey, Вы писали:


L>>Задача: реализовать IPaymentProcessor

·>Я бы как-то так сделал:

·>
·> public interface IBusinessRule
·> {
·>        bool Validate();
·> }

·> class Rule1 : IBusinessRule
·> {
·>      public Rule1(string name) { ... }
·>      bool Validate() { ... }
·> }

·> class Rule2 : IBusinessRule
·> {
·>      public Rule1(int month, int year) { ... }
·>      bool Validate() { ... }
·> }

·> class CompositeBusinessRule : IBusinessRule
·> {
·>      const IBusinessRule rules;
·>      CompositeBusinessRule(IBusinessRule rules...) {this.rules = rules;}
·>      bool Validate() {
·>           foreach(var r in rules) if(!r.Validate()) { return false; }
·>           return true;
·>      }
·> }

·> interface IPaymentProcessor
·> {
·>    bool MakePayment(CreditCard card);
·> }

·> class CreditCardValidatorFactory
·> {
·>    IBusinessRule createValidation(CreditCard card)
·>        {
·>           return new CompositeBusinessRule(
·>                 new Rule1(card.Name),
·>                 new Rule2(card.Month, card.Year)
·>           );
·>        }
·> }

·> interface IPaymentProcessor
·> {
·>    bool MakePayment(CreditCard card);
·> }

·> class MyPaymentProcess : IPaymentProcessor
·> {
·>    const CreditCardValidatorFactory validatorFactory;
·>        MyPaymentProcess(CreditCardValidatorFactory validatorFactory) { this.validatorFactory = validatorFactory;}

·>    public bool MakePayment(CreditCard card)
·>     {
·>        IBusinessRule validator = validatorFactory.createValidation(card);
·>        if(!validator.Validate()) { return false; }
·>        return true;
·>    }
·> }  

·>

·>А следующим шагом я бы изменил IBusinessRule чтобы они ещё репортили ошибку c подробностями что случилось, а не просто true/false.

Мое решение похоже, только одним классом RulesFactory, не плодя сущности. С методом
Register(Func<CreditCard, IRule> newRuleCreator) { _listOfRules.Add(newRuleCreator); }

Ну и далее в конструкторе фабрики регистрируем все нужные инстансы IRule, и в случае чего в рантайме тоже вызываем Register для новых правил.

·>ЗЫЖ Ninject — фтопку, как и все IoC-фреймворки.

С этого места по подробнее пожалуйста. Это чуть ли не первый вопрос на каждом интервью. Рассказать про DI. А с ним и про Ninject.
Re[3]: Фабрика объектов с разными конструкторами
От: Lexey Россия  
Дата: 08.11.16 10:42
Оценка:
Здравствуйте, licedey, Вы писали:

L>·>ЗЫЖ Ninject — фтопку, как и все IoC-фреймворки.

L>С этого места по подробнее пожалуйста. Это чуть ли не первый вопрос на каждом интервью. Рассказать про DI. А с ним и про Ninject.

Ниже есть тема
Автор: IQuerist
Дата: 27.07.16
, в которой довольно много про DI и контейнеры.
Если кратко, то чаще всего контейнеры для DI нафиг не нужны, а их повсеместное втыкание лишь усложняет понимание и поддержку кода.
"Будь достоин победы" (c) 8th Wizard's rule.
Re[3]: Фабрика объектов с разными конструкторами
От: · Великобритания  
Дата: 08.11.16 10:45
Оценка:
Здравствуйте, licedey, Вы писали:

L>·>А следующим шагом я бы изменил IBusinessRule чтобы они ещё репортили ошибку c подробностями что случилось, а не просто true/false.

L>Мое решение похоже, только одним классом RulesFactory, не плодя сущности. С методом
L>
L>Register(Func<CreditCard, IRule> newRuleCreator) { _listOfRules.Add(newRuleCreator); }
L>

Да какая разница. Вместо явного типа CreditCardValidatorFactory ты используешь догадайся-что-я-имел-в-виду Func<CreditCard, IRule>.
Если так рассуждать, то и IRule можно заменить, пиши уж сразу Func<CreditCard, Func<bool>>.

L>Ну и далее в конструкторе фабрики регистрируем все нужные инстансы IRule, и в случае чего в рантайме тоже вызываем Register для новых правил.

Фи.

L>·>ЗЫЖ Ninject — фтопку, как и все IoC-фреймворки.

L>С этого места по подробнее пожалуйста. Это чуть ли не первый вопрос на каждом интервью. Рассказать про DI. А с ним и про Ninject.
Вкратце: DI+CI — хорошо, IoC-containers — плохо.
Подробности: О "наивном" DI и об архитектурном бессилии
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[4]: Фабрика объектов с разными конструкторами
От: licedey  
Дата: 08.11.16 21:01
Оценка:
Здравствуйте, ·, Вы писали:

·>Здравствуйте, licedey, Вы писали:


L>>·>А следующим шагом я бы изменил IBusinessRule чтобы они ещё репортили ошибку c подробностями что случилось, а не просто true/false.

L>>Мое решение похоже, только одним классом RulesFactory, не плодя сущности. С методом
L>>
L>>Register(Func<CreditCard, IRule> newRuleCreator) { _listOfRules.Add(newRuleCreator); }
L>>

·>Да какая разница. Вместо явного типа CreditCardValidatorFactory ты используешь догадайся-что-я-имел-в-виду Func<CreditCard, IRule>.
·>Если так рассуждать, то и IRule можно заменить, пиши уж сразу Func<CreditCard, Func<bool>>.

Разница в избавлении от лишнего класса, как в решении выше и использовании паттерна Factory. По моему из имени параметра и названии класса понятно, "что я имел ввиду"
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.