Какой шаблон проектирования используется для создания нескольких симуляций?
У меня есть симуляция, которая работает на определенной высоте и определенной температуре:
interface IGeneratable
{
string Name { get; }
void Generate();
}
interface ISimulation : IGeneratable
{
int Height { get; }
int Temperature { get; }
}
Процесс Generate()
для моделирования обычно включает в себя несколько этапов:
void Generate()
{
Step1();
Step2();
Step3();
}
Теперь пользователь может указать несколько высот и/или несколько температур.
В этом случае генерируются множественные симуляции (субимоляции), по одному на каждую комбинацию высоты/температуры.
interface IMultiSimulation : IGeneratable
{
ISimulation[] SubSimulations { get; }
}
Однако в этом случае метод Sub-simulation Generate() отклоняется от порядка Step1, Step2, Step3:
- Если указано несколько температур, то
Step2()
необходимо выполнить только один раз для всех подмодулей, а не для температуры (т.е. один раз для мультимоделирования).
- Если указано несколько высот, то:
-
Step1()
предварительно вычисляется сначала для всех под-симуляций.
- Затем выполняются шаги Step2, Step3 и т.д.
- Возможно иметь большое симуляцию с несколькими высотами и несколькими температурами. Это означает, что необходимо выполнить 2 вышеуказанных критерия.
Общие примечания
- Этап реализации инкапсулирован в
IStep
, который реализует IGeneratable
. Таким образом, для моделирования можно, например, вернуть список шагов.
- Количество шагов может быть довольно большим.
Я пытаюсь использовать шаблон декоратора, но без успеха.
Я ищу подходящий шаблон с масштабируемым решением, которое будет обрабатывать генерацию одиночного моделирования, а также несколько симуляций.
Спасибо.
Ответы
Ответ 1
В вашем случае я бы использовал композитный шаблон дизайна.
Метод generate будет проверять, имеет ли он какие-либо компоненты. Если это не так, просто вызывается
void Generate()
{
Step1();
Step2();
Step3();
}
но если у него есть компоненты, это означает, что он имеет несколько симуляций. Тогда код будет выглядеть примерно так:
void Generate()
{
if(this.simulations.Count==0)
{
Step1();
Step2();
Step3();
}
else
{
if(multipleHeights)
{
precomputeStep1();
if(multipleHeights)
{
createSingletonForStep2(this);
}
else
{
Step2();
}
Step3();
}
}
}
И для шага 2 я бы просто вызвал одноэлемент, который получает этот композит в качестве параметра, поэтому для этой группы симуляций будет только один шаг2.
Ответ 2
Интерфейсы:
interface IGeneratable
{
string Name { get; }
void Generate();
}
interface IGeneratableOnce : IGeneratable
{
bool HasRunned { get; set; }
}
interface ISimulation : IGeneratable
{
int Height { get; }
int Temperature { get; }
IMultiSimulation MultiSimulation{ get; }
IGeneratable[] Steps{ get; }
}
interface IMultiSimulation : IGeneratable
{
ISimulation[] SubSimulations { get; }
}
Типичная генерация MultiSimulation:
void Generate(){
for (ISimulation simulation in SubSimulations){
simulation.Generate();
}
}
Типичная генерация ISimulation:
void Generate(){
for (IGeneratable step in Steps){
step.Generate();
}
}
Исимуляция Создайте, избегая второго шага дважды:
void Generate(){
for (int i=0;i<Steps.Length;i++){
IGeneratable step = Steps[i];
if (i!=1){
if (step is IGeneratableOnce && !(step as IGeneratableOnce).HasRunned){
step.Generate();
step.HasRunned = true;
}
}else{
step.Generate();
}
}
}
Вы можете добавить несколько других флагов, если хотите, возможно, даже какой-то метод вроде CanRun (int Height, int Temperature), если ваша логика становится слишком сложной.
Однако в вашей ситуации, я считаю, вы должны использовать составную вариацию шаблона, как этот образец кода.
EDIT: Здесь еще один интересный шаблон, который вы можете использовать
Ответ 3
Ваша задача не такая маленькая, поэтому ответ - это не один шаблон дизайна, а несколько. Я лично не стал бы акцентировать внимание на шаблонах, а скорее на интуитивной и интенциональной реализации (например, я написал об этом здесь: http://www.tutisani.com/software-architecture/intuitive-object-models.html). Я думаю, что ваш дизайн не является интуитивным и самоописательным, поэтому вы не решаете правильную проблему, задавая вопрос, который вы задали.
В любом случае, поскольку вы просите идентифицировать образцы дизайна, я также помогу вам в этом.
- Факт, что все ваши производные типы (в частности, интерфейсы) реализуют IGeneratable, который называется шаблоном проектирования
Super Type
.
- Как предполагалось, симуляция, содержащая другие симуляции внутри, представляет собой шаблон
Composite
. Однако это не совсем точно, так как IMultiSimulation не реализует ISimulation. В любом случае это какой-то составной компонент, поскольку как родитель, так и дети реализуют IGeneratable по крайней мере.
- IStep звучит как шаблон
Strategy
, но, я думаю, вы не используете его правильно.
Теперь я хочу предложить вам пересмотреть свой подход к дизайну, потому что ваши интерфейсы не интуитивно понятны. Вот проблемы, которые я вижу, которые вам нужно передумать:
- Исимуляция имеет высоту и температуру, а также имеет Generate(). Generate(), скорее всего, предполагается использовать Height and Temperature - то, как я понял ваше описание, но тогда это не правильный способ выразить это. Если Generate() зависит от высоты и температуры, передайте их как аргументы и не определяйте их как свойства. Кроме того, интерфейс может лучше выражать поведение, а не состояние. Свойства представляют состояние, которое я хотел бы выразить как класс, а не интерфейс.
- Если симуляция будет выполнять шаги, не определяйте их сами по ISimulation - это опять не так интуитивно понятный дизайн. Передайте их как аргументы, и это сделает его шаблоном проектирования стратегии (почему я сказал выше, что он не реализован правильно).
Я бы пошел дальше, но я не знаю всей картины. Из того, что вы выразили, ваша представленная реализация неверна. Пожалуйста, подумайте.
Ответ 4
мне кажется, что существует очень конкретный прецедент для реализации, поэтому я предлагаю использовать класс, который будет включать в себя memlement для Generate() (надеюсь, я правильно понял требования)
class Simulation
{
string Name { get; }
int[] Heights { get; }
int[] Temperatures { get; }
void Generate() {
for (int i = 0; i < Temperatures.Count; i++) {
for (int j = 0; j < Heights.Count; j++) {
GenerateStep1();
}
GenerateStep2();
GenerateStep3();
}
}
}