Возможно, вам нужно удалить зависимости из вашего кода. Чрезмерность из вашего кода существует в двух отношениях:
- у вас избыточный код (интерфейсы)
- у вас чрезмерные ограничения (перечисления)
Наконец, я получил это в диалоге с Адамом, который исключает выбросы исключений, необходимость двух операторов switch, двух перечислений, сохраняя при этом закрытия пулов и устраняя возможные ошибки в коде. Для каждого оператора switch (каждой пары реализации интерфейса) необходимо реализовать собственный статический метод, правильно создающий экземпляр класса Pool:
public interface IPool
{
void Execute();
}
public class Pool : IPool
{
private Pool() { }
public IPickListGenerator PickListGenerator { set; private get; }
public IQuestionIsAnswerableDeterminer IsQuestionIsAnswerableDeterminer { set; private get; }
public static IPool GetSportsGame()
{
return new Pool
{
PickListGenerator = new SportsPicklistGenerator(),
IsQuestionIsAnswerableDeterminer = new GameQuestionIsAnswerableDeterminer()
};
}
public static IPool GetSportsEntertainment()
{
return new Pool
{
PickListGenerator = new SportsPicklistGenerator(),
IsQuestionIsAnswerableDeterminer = new EntertainmentPicklistGenerator()
};
}
public void Execute()
{
IsQuestionIsAnswerableDeterminer.Execute();
PickListGenerator.Execute();
}
}
--- История этого поста, приведшая к этому решению:
Вы можете улучшить свой код, упростив код, потому что в вашей реализации класс Pool ограничен перечислениями, и если это так, класс Pool не является расширяемым. Вам, вероятно, придется переписывать SetPoolSpecificInterfaces () снова и снова, когда появятся новые требования и реализация интерфейса. Таким образом, самым слабым местом текущего проекта является конкретный метод SetPoolSpecificInterfaces () и, если это так, не расширяемый класс Pool.
Если это то, что вам нужно, то интерфейсы на самом деле не нужны. В другом случае вы не будете зависеть от количества реализаций интерфейса (которое на самом деле исправлено соответствующим перечислением), поэтому, вероятно, его можно упростить до следующего кода (я исправил проблемы), сняв эти ограничения:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// Example usages:
var pool = new Pool
{
PickListGenerator = new SportsPicklistGenerator(),
IsQuestionIsAnswerableDeterminer = new GameQuestionIsAnswerableDeterminer()
};
pool.ExecuteIsQuestionIsAnswerableDeterminer();
pool.ExecutePickListGenerator();
}
}
public class Pool
{
public IPickListGenerator PickListGenerator { set; private get; }
public IQuestionIsAnswerableDeterminer
IsQuestionIsAnswerableDeterminer { set; private get; }
public void ExecuteIsQuestionIsAnswerableDeterminer()
{
IsQuestionIsAnswerableDeterminer.Execute();
}
public void ExecutePickListGenerator()
{
PickListGenerator.Execute();
}
}
}
Вы, вероятно, можете остановиться здесь, но что, если вы всегда будете вызывать ExecuteIsQuestionIsAnswerableDeterminer () перед вызовом ExecutePickListGenerator ()? тогда вы можете изменить код следующим образом:
public class Pool
{
public IPickListGenerator PickListGenerator { set; private get; }
public IQuestionIsAnswerableDeterminer
IsQuestionIsAnswerableDeterminer { set; private get; }
public void Execute()
{
// improvements, seen by Arnis
if (IsQuestionIsAnswerableDeterminer == null)
{
thrown new ArgumentException("IsQuestionIsAnswerableDeterminer");
}
if (PickListGenerator == null)
{
thrown new ArgumentException("PickListGenerator");
}
IsQuestionIsAnswerableDeterminer.Execute();
PickListGenerator.Execute();
}
}
Если это так, вы можете написать что-то похожее на это:
var pool = new Pool
{
PickListGenerator = new SportsPicklistGenerator(),
IsQuestionIsAnswerableDeterminer = new GameQuestionIsAnswerableDeterminer()
};
pool.Execute();
// reuse the same class logic in Pool class in Execute method
pool.PickListGenerator = new GamePickListGenerator();
pool.Execute();
// reuse the same class logic in Pool class in Execute method
pool.IsQuestionIsAnswerableDeterminer = new RoundQuestionIsAnswerableDeterminer();
pool.Execute();
Как сказал @ Adam Robinson, это меняет некоторую логику пула (чтобы исправить это, вы можете использовать реализацию близкого пула), так что вы можете исправить это таким образом, добавив новый интерфейс, IPool, добавив приватный конструктор в класс Pool и static логическая реализация, которая полностью устранит необходимость в легком утверждении:
public interface IPool
{
void Execute();
}
public class Pool : IPool
{
private Pool() { }
public IPickListGenerator PickListGenerator { set; private get; }
public IQuestionIsAnswerableDeterminer IsQuestionIsAnswerableDeterminer { set; private get; }
public static IPool GetSportsGame()
{
return new Pool
{
PickListGenerator = new SportsPicklistGenerator(),
IsQuestionIsAnswerableDeterminer = new GameQuestionIsAnswerableDeterminer()
};
}
public static IPool GetSportsEntertainment()
{
return new Pool
{
PickListGenerator = new SportsPicklistGenerator(),
IsQuestionIsAnswerableDeterminer = new EntertainmentPicklistGenerator()
};
}
public void Execute()
{
IsQuestionIsAnswerableDeterminer.Execute();
PickListGenerator.Execute();
}
}
Это отредактировал Арнис:
public class Pool{
private readonly IPickListGenerator _generator;
private readonly IQuestionIsAnswerableDeterminer _determiner;
public Pool(IPickListGenerator generator,
IQuestionIsAnswerableDeterminer determiner){
if(determiner==null||generator==null)
throw new ArgumentNullException();
_generator=generator;
_determiner=determiner;
}
public void Execute(){
_determiner.Execute();
_generator.Execute();
}
}
var generator=new SportsPicklistGenerator();
var determiner=new GameQuestionIsAnswerableDeterminer();
var pool = new Pool(generator, determiner);
pool.Execute();