Супер класс зная тип своего ребенка? Безусловно, есть лучший способ


Я работаю на небольшой проект, который делает математические расчеты на основе выбранных данных в jtable. Цель состоит в том, чтобы сделать программу достаточно адаптированы для добавления новых математических вычислений в будущем. Для справки, некоторые текущие расчеты: рассчитать среднее (среднее) набора данных; вычисление процентиля для каждого элемента в наборе исходных данных; вычисление наименьших квадратов линейная регрессия (линейная функция лучше всего подходят) для набора точек данных.

Мой нынешний дизайн мыслительный процесс заключается в том, что, чтобы сделать вещи математику коммунальные услуги гибкие, там должен быть некоторый тип базового класса для анализа данных, которые служат входом и выходом для некоторых типа performAnalysis функции в базовый класс для всех классов анализа. Это привело меня к каркасной конструкцией следующим образом:

public enum AnalysisDataType {
    Scalar,
    Set,
    Map
}

public interface IAnalysisData {
    AnalysisDataType getType();
}

public interface IAnalaysisDataScalar extends IAnalysisData {
    double getValue();
}

public interface IAnalaysisDataSet extends IAnalysisData {
    int getCount();
    IAnalysisData getData(int index);
}

public interface IAnalaysisDataMap extends IAnalysisData {
    IAnalysisData getDomain();
    IAnalysisData getCodomain();
}

public interface IDataAnalysis {
    AnalysisDataType getInputDataType();
    AnalysisDataType getOutputDataType();

    IAnalysisData performAnalysis(IAnalysisData inputData);
}

То, что для расчета означать будет:

public class DataAnalysisMean implements IDataAnalysis {
    AnalysisDataType getInputDataType() { return AnalysisDataType.Set; }
    AnalysisDataType getInputDataType() { return AnalysisDataType.Scalar; }

    IAnalysisData performAnalysis(IAnalysisData intputData) {

        IAnalysisDataSet inputDataSet = (IAnalysisDataSet)inputData;
        double sum = 0;

        for (int i = 0; i < inputDataSet.getCount(); i++) {
            IAnalysisData dataItem = inputDataSet.getData(i);
            IAnalysisDataScalar dataItem = (IAnalysisDataScalar)dataItem;
            sum += dataItem.getValue();
        }

        return new IAnalysisDataScalar() {
            @Override
            double getValue() {
                return sum / inputDataSet.getCount();
            }

            @Override
            AnalysisDataType getType() {
                return AnalysisDataType.Scalar;
            }
        };
    }
}

Я понимаю, что немного больше работы нужно идти в "описании" входные и выходные данные, потому что ни где я упоминал, что входной набор содержащихся скаляры, а - а у меня уже есть идея, как решить, что одна - я чувствую, что весь подход программистские.

Мысль, лежащая в основе этого подхода заключается в том, что код, используя взаимодействие с этими математики коммунальные услуги могут запросить IDataAnalysis интерфейс, чтобы определить, что ожидаемый ввод и вывод и не ввод по мере необходимости и анализа результатов надлежащим образом. Это позволит нам просто нужно бросить дополнительные функции в более позднее время, без необходимости добавлять дополнительную логику контроллера, чтобы связать его.

Я чувствую, что его неправильно для родительского класса или интерфейса в этом деле - узнать о своих возможных детей классы (интерфейсы) через AnalysisDataType перечисление и метод gettype метод. Как всегда с ОО программирования, конечно, просто еще один слой абстракции или какой тип нужен, хотя, возможно, я просто пропустила на какой-то другой шаблон проектирования, который решает этот точный проблема.

В любом случае, если у кого есть советы о том, что я могу сделать, чтобы лучше организовать это, я буду вам очень признательна. Я хотел бы услышать, как неправильно мои мысли и узнать лучший способ.



332
4
задан 11 октября 2011 в 01:10 Источник Поделиться
Комментарии
1 ответ

Во-первых, я получаю некоторые сообщения об ошибках, когда я положил это в компилятор.
Мне пришлось заменить анонимный внутренний класс, который возвращается performAnalysis с вспомогательный класс. Я не фанат вспомогательные классы, такие как это, поэтому было бы неплохо, если кто-нибудь есть идея получше.

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

interface IDataAnalysis<InputType extends IAnalysisData, OutputType extends IAnalysisData> {

// public Class<?> getInputDataType( );
// public Class<?> getOutputDataType( );

OutputType performAnalysis(InputType inputData);
}

public class DataAnalysisMean implements IDataAnalysis<IAnalysisDataSet, IAnalysisDataScalar> {

//
// public Class<?> getInputDataType( ) { return IAnalysisDataSet.class; }
// public Class<?> getOutputDataType( ) { return IAnalysisDataScalar.class; }

public IAnalysisDataScalar performAnalysis(IAnalysisDataSet inputData) {

IAnalysisDataSet inputDataSet = (IAnalysisDataSet)inputData;
double sum = 0;

for (int i = 0; i < inputDataSet.getCount(); i++) {
IAnalysisData dataItem = inputDataSet.getData(i);
IAnalysisDataScalar dataItem2 = (IAnalysisDataScalar)dataItem;
sum += dataItem2.getValue();
}

return new HelperClass( inputDataSet, sum );
}

private class HelperClass implements IAnalysisDataScalar
{
IAnalysisDataSet inputDataSet;
double sum = 0;

HelperClass( IAnalysisDataSet inputSet, double sum )
{
this.inputDataSet = inputSet;
this.sum = sum;
}

@Override
public double getValue() {
return sum / inputDataSet.getCount();
}

@Override
public AnalysisDataType getType() {
return AnalysisDataType.Scalar;
}
}
}

2
ответ дан 12 октября 2011 в 08:10 Источник Поделиться