2016-09-17 2 views
2

Я создаю систему управления контентом с помощью Java, у меня есть класс для выражения сущности и класс для выражения поля внутри объекта.Свойство класса Java, которое может поддерживать разные типы

В настоящее время мой класс Field является массивом String для хранения всех значений.

Мой класс выглядит следующим образом:

public class Field implements Serializable { 
    private UUID key; 
    private String name; 
    private ArrayList<String> values; 
    private Integer maxValues; 
    private ValueType type; 
    private String code; 

    public enum ValueType { 
     INT, 
     VARCHAR, 
     DATE, 
     BOOLEAN 
    } 

    public void addValue(String value){ 
     if (this.values.size() < this.maxValues){ 
      this.values.add(value); 
     } 
    } 

    public ArrayList<String> getValues(){ 
     return this.values; 
    } 
} 

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

public ArrayList<Integer> getIntegerValues(){ 

    ArrayList<Integer> integerValues = new ArrayList<Integer>(); 


    values.forEach(
     (v) -> { 

      Integer intValue = Integer.parseInt(v); 

      integerValues.add(intValue); 

     } 
    ); 

    return integerValues; 
} 

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

Есть ли у кого-нибудь идеи, как я могу написать это лучше.

+0

Похоже, вы хотите использовать generics – Kelvin

+0

Может ли одно поле содержать несколько типов? –

+0

Никакое поле никогда не будет содержать разные типы. –

ответ

0

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

Ваш конкретный класс определит значения для общего значения. Это удовлетворяет открытому замкнутому принципу.

public interface FieldType<T> { 
    void addValue(T value); 
    ArrayList<T> getValues(); 
} 

public abstract class Field<T> implements FieldType<T>, Serializable { 
    private UUID key; 
    private String name; 
    protected ArrayList<T> values; 
    private Integer maxValues; 
    private String code; 

    public abstract void addValues(); 

    public ArrayList<T> getValues(){ 
     return this.values; 
    } 
} 

public class FloatField extends Field<Float> { 

    @Override 
    public void addValue(Float value) { 
     this.values.add(value); 
    } 

    @Override 
    public ArrayList<Float> getValues() { 
     return this.values; 
    } 
} 
1

Вот пример того, как можно использовать дженерики:

public class Field<T> implements Serializable { 
    private UUID key; 
    private String name; 
    private ArrayList<T> values; 
    private Integer maxValues; 
    private String code; 

    public void addValue(T value) { 
     if (this.values.size() < this.maxValues){ 
      this.values.add(value); 
     } 
    } 

    public ArrayList<T> getValues(){ 
     return this.values; 
    } 
} 
+0

Мне нравится эта идея, я думаю, что она решит мои проблемы, но в то же время представит еще одну проблему не знать тип при возврате этого, я думаю, что буду выполнять строгую проверку типов при добавлении значений в поле, соответствующее типу объекта , –

+0

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

1

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

Проблема с перечислениями: они очень полезны для «моделей», которые имеют очень небольшой шанс на изменение в будущем. Потому что обычно происходит: для каждого перечисления, которое у вас есть, вы будете создавать переключатель; чтобы реализовать различное поведение для ваших разных констант перечисления. Это может показаться не такой проблемой, но это ... когда вы понимаете, что вам нужно добавить еще один тип. Затем вам нужно найти все эти ключи и решить, как обрабатывать новую константу enum.

Вместо этого ваша конструкция должна управляться Open/Closed principle: открыть для изменения; но закрыт для модификации. В ОО, что чаще всего проявляется в использовании абстрактных классов, как

public abstract class ValueType { 
    ... which has some ABSTRACT methods 
    ... and probably some FINAL methods 

абстрактные методы, где вы реализуете это поведение, которое должно быть различным для различных дочерних классов; и FINAL-методы - это те, которые «исправляют» это поведение, которые должны быть одинаковыми для каждого экземпляра этих классов.

И затем вы идете вперед и создаете определенные подклассы, например IntValue extends ValueType и так далее.

И почему это лучше? Очень просто: добавление нового типа ValueType означает ... создание нового подкласса - без необходимости касаться любого существующего кода. Таким образом, такой дизайн составляет open для изменения (добавление новых типов!), Но закрыт для модификации (поскольку добавление нового типа ничего не меняет в других существующих классах).

+0

Мне очень нравится эта идея, она сможет принудительно добавить ValueType в конструктор, но если абстрактному методу addValue и getValue нужно будет использовать дженерики? –

+0

Несмотря на то, что я проверял ответ на общий ответ, я написал код для реализации дженериков, и я не считаю его лучшим решением, он нарушает открытый закрытый принцип, как вы упомянули, я думаю, что абстракция может потребоваться на класс Field, так что VarcharField/IntegerField/FloatField расширяет поле, попробует реализацию и посмотрит, как это чувствует, но, на мой взгляд, похоже, что она предложит большую гибкость в дизайне, проще добавить новые типы. –

+0

Я рад, что вы нашли полезную информацию. Если возможно, я бы рекомендовал вам поговорить с опытными людьми лицом к лицу; таким проблемам просто нужно много думать; и обмен идеями часто помогает. – GhostCat

Смежные вопросы