Come memorizzare molte variabili globali?

2

Ho circa 30 oggetti "non cambianti" (la quantità di essi è definitiva, non è possibile aggiungere o rimuovere altro). Ogni oggetto ha un id e alcuni booleani che descrivono cosa è l'oggetto e cosa no. Ora, ogni oggetto ha una variabile che deve essere cambiata in fase di runtime. Molte di queste variabili sono solo un numero intero, ma alcune hanno anche stringhe, liste, ecc.

Ora mi chiedo come implementarlo. Il mio attuale tentativo è un enum con gli oggetti dati, le loro proprietà e metodi per cambiarli (per la variabile ho scelto solo oggetto come tipo, per memorizzare sia interi che elenchi). Funziona, ma non sembra il modo corretto, OO, per farlo. Quali sono le alternative? Il linguaggio di programmazione è Java, se questo è importante.

Ecco il mio tentativo (un po 'più complicato di quello che ho spiegato sopra):

public enum StatusInfos {

    THING_1("id0", false ,false, false, NOT_UPGRADABLE),

    THING_1_WITH_HAT("id1", true, false, false, NOT_UPGRADABLE),
    ANOTHER_THING("id2", false, false, false, NOT_UPGRADABLE),
    GREEN_THING("id3", true, false, false, NOT_UPGRADABLE),
    TALKING_DUCK("id4", true, false, false, NOT_UPGRADABLE);


    private final String id;
    private final Boolean hasAdditionalValue;
    private Double value;
    private Double additionalValue;
    private boolean needsDouble;
    private boolean needsPerCent;


    private Integer upgradeCategory;

    private Object additionalValue;

    StatusInfos(String id, Boolean hasAdditionalValue, boolean needsDouble, boolean needsPerCent, Integer upgradeCategory){
        this.id = tag;
        this.hasAdditionalValue = hasAdditionalValue;
        this.needsDouble = needsDouble;
        this.needsPerCent = needsPerCent;
        this.upgradeCategory = upgradeCategory;
    }


    public String id(){
        return id;
    }
    public Double value(){
        return value;
    }
    public void setValue(Double value){
        this.value = value;
    }
    public boolean hasAdditionalValue(){
        return hasAdditionalValue;
    }

    public Double additionalValue(){
        return additionalValue;
    }
    public void setAdditionalValue(Double newAdditionalValue){
        additionalValue = newAdditionalValue;
    }
    public boolean hasSpecialValue(){
        return false;
    }

    public Object specialValue(){
        return null;
    }
    public void setSpecialValue(Object newValue){
        return;
    }

    public boolean needsNumbersAfterComma(){
        return needsDouble;
    }

    public boolean needsPerCent(){
        return needsPerCent;
    }

    public Integer getUpgradeCategory() {
        return upgradeCategory;
    }

    public Object getAdditionalValue(){
       return additionalValue;
    }
    public void setAdditionalValue(Object additionalValue)
       this.additionalValue = additionalValue;
    }
}
    
posta Namnodorel 19.05.2016 - 14:51
fonte

3 risposte

3

Definirei una classe contenente tutte le cose comuni (la lista dei booleani è la stessa tra questi oggetti?) e i loro getter e setter, quindi sottoclasse a seconda del tipo di oggetto modificabile all'interno, quindi metterli tutti in un contenitore ottimizzato per come si guardano queste cose (id, probabilmente).

In questo modo hai uno globale.

    
risposta data 19.05.2016 - 15:23
fonte
1

Per me hai 2 modi:

  • Un registro: una classe che conterrà tutta la tua variabile globale da sé stessa e avrà getter su proerty di sola lettura e getter / setter su proprietà read / write.
  • Utilizzare un framework che fornisce l'iniezione di dipendenza, ad esempio Spring. Di default tutti i bean istanziati da Spring sono singleton e li si può iniettare (per costruttore o setter) ad altre classi gestite da Spring. Questo aggiunge qualche configurazione ma rimuove un sacco di codice bloat. Spring è molto utile con l'applicazione Web ma si adatta perfettamente anche se non è web.
risposta data 20.05.2016 - 10:04
fonte
0

Vorrei provare un approccio come questo:

/*
 * First, have a class which whatever your constants have in common.
 */
public class StatusInfos {
    String id;

    /*
     * Then create a subclass for every different object:
     */
    public class IntStatusInfo extends StatusInfos {
        int value;

        public int getValue() {
            return value;
        }
    }

    public class DoubleStatusInfo extends StatusInfos {
        double value;

        public double getValue() {
            return value;
        }
    }

    /*
     * You can then define your constants like this:
     */
    public static final StatusInfos THING_1 = new StatusInfos().new IntStatusInfo() {
        {
            id = "id1";
            value = 1;
        }
    };

    public static final StatusInfos THING_2 = new StatusInfos().new DoubleStatusInfo() {
        {
            id = "id2";
            value = 1.2;
        }
    };
}

BTW, sarà più facile se rendi il tuo IntStatusInfo , DoubleStatusInfo , ... in propri file di classe, non in classi interne.

Modifica: sembra che tu stia scrivendo una sorta di configurazione. Se sì, hai dato un'occhiata se puoi usare Configurazione di Apache Commons ?

Modifica 2: come per il tuo commento: quindi vuoi poter iterare sui campi per elaborarli. Ho sempre quel codice "ridondante", perché di solito il codice non è veramente ridondante. Tutti i campi sono un po 'diversi. Invece, ho un chiaro modello di dati nel mio oggetto allora. Di solito ho una funzione per l'output-conversione / salvataggio dell'oggetto (vedere toMap() nell'esempio) e un costruttore per l'input-conversione dell'oggetto. Ho spesso molti di loro (per mappare, json, Android intenti extra, xml, ...) e li ho sempre nella classe che deve essere serializzata o deserializzata.

public class PlayerStatus {
    private final Set<Capability> capabilities = new HashSet<Capability>();
    private double height = 1.7;
    private int life;
    private int points;
    // ... 26 more

    /** 
     * Explicit default constructor.
     */
    public PlayerStatus() {}

    /**
     *  Constructor to restore an object.
     */
    public PlayerStatus(Map<String, String> data) {
        life = Integer.valueOf(data.get("life"));
        points = Integer.valueOf(data.get("points"));
        height = Double.valueOf(data.get("height"));
        for (String capability : data.get("capabilities").split(","))
            capabilities.add(Capability.valueOf(capability));
        // ... 26 more
    }

    /**
     * Getters and setters, as needed.
     */
    public void addCapability(Capability capability) {
        capabilities.add(capability);
    }

    public void addPoints(int points) {
        this.points += points;
    }

    public double getHeight() {
        return height;
    }

    public double getLifePercent() {
        return (double) life / 100;
    }

    public int getPoints() {
        return points;
    }

    public boolean hasCapability(Capability capability) {
        return capabilities.contains(capability);
    }

    public void looseCapability(Capability capability) {
        capabilities.remove(capability);
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public void setLifePercent(double value) {
        life = (int) Math.round(100d * value);
    }

    /**
     * Function to output-convert the object.
     */
    public Map<String, String> toMap() {
        Map<String, String> result = new HashMap<String, String>((int) Math.ceil(30 / 0.75));
        result.put("life", Integer.toString(life));
        result.put("points", Integer.toString(points));
        result.put("height", Double.toString(height));
        StringBuilder capabilitiesStringBuilder = new StringBuilder(16 * capabilities.size());
        for (Capability capability : capabilities) {
            capabilitiesStringBuilder.append(capability.toString());
            capabilitiesStringBuilder.append(",");
        }
        result.put("capabilities", capabilitiesStringBuilder.toString());
        // ... 26 more
        return result;
    }
}
    
risposta data 19.05.2016 - 16:03
fonte

Leggi altre domande sui tag