Переопределение кода типа рефакторинга

В настоящее время я ищу фрагмент кода, который сериализует/десериализует данные.

Структура класса выглядит примерно так:

public class Field
{
    public abstract void writeField(DataOutputStream out);

    public abstract int getFieldID();

    ...

    protected static final int INT_FIELD = 1;
    protected static final int BOOL_FIELD = 2;

    ...

    public void write(DataOutputStream out)
    {
        out.writeInt(getFieldID());
        writeField(out);
    }

    ...
}

public class IntField extends Field
{
    public int v;

    public void writeField(DataOutputStream out)
    {
        out.writeInt(v);
    }

    public int getFieldID()
    {
        return Field.INT_FIELD;
    }
}

Мне кажется, что реализация getFieldID не самая лучшая.

Написание абстрактного метода для возврата уникального идентификатора для этого класса кажется неприятным запахом.

Есть ли лучшие способы реализовать это?


person Brad    schedule 14.05.2012    source источник
comment
Смотрите мой ответ, если это то, что вы хотите.   -  person nnhthuan    schedule 14.05.2012


Ответы (3)


Перечислять специфичные для подкласса константы в базовом классе — не лучшая идея, потому что в идеале суперкласс не должен знать о своих подклассах. Простое перечисление констант в базе не так плохо, как использование их для различения подклассов в коде базового класса.

В идеале вы должны переместить константы в соответствующие подклассы. Если вы не можете сделать это, не сломав компиляцию, вы действительно наткнулись на главного кандидата на рефакторинг.

person Sergey Kalinichenko    schedule 14.05.2012
comment
Я предполагаю, что проблема в том, что вы можете столкнуться с идентификаторами полей, которые будут конфликтовать. Поскольку нет централизованного списка идентификаторов полей, вы можете в конечном итоге объявить идентификатор поля одним и тем же в двух отдельных подклассах. - person Brad; 14.05.2012

Вы можете определить класс с помощью Generics. Так:

Поле

import java.io.DataOutputStream;

public abstract class Field<T extends Object> {
    public abstract void writeField(DataOutputStream out);
    public abstract T getValue();
    public abstract Class<T> getFieldClass();
}

IntField

import java.io.DataOutputStream;
import java.io.IOException;

public class IntField extends Field<Integer> {
    public Integer v;

    @Override
    public void writeField(DataOutputStream out) {
        try {
            out.writeChars(v.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Integer getValue() {
        return v;
    }

    @Override
    public Class<Integer> getFieldClass() {
        return Integer.class;
    }
}
person nnhthuan    schedule 14.05.2012
comment
При считывании данных обратно из файла, как вы определяете, какой объект создать, чтобы считать правильную информацию? В файле нет идентифицирующей информации, верно? - person Brad; 14.05.2012
comment
Вы можете определить структуру самостоятельно, чтобы определить тип файла. :) - person nnhthuan; 14.05.2012

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

У вас может быть интерфейс, который реализован в классе реализации, где все методы, объявленные в интерфейсе, реализованы в классе реализации. Этот метод и другая разновидность наследования известны как наследование интерфейса. Это уменьшает тесную связь между суперклассом и подклассом.

person Sanath    schedule 14.05.2012