2010-12-12 15 views
7

Qual è il modo migliore per condividere i dati tra classi separate in Java? Ho un sacco di variabili che vengono utilizzate da classi diverse in file separati in modi diversi. Vorrei cercare di illustrare una versione semplificata del mio problema:Come condividere i dati tra classi separate in Java

Questo era il mio codice prima:

public class Top_Level_Class(){ 
    int x, y; 

    // gets user input which changes x, y; 
    public void main(){ 
     int p, q, r, s; 
     // compute p, q, r, s 
     doA(p,q,r); 
     doB(q,r,s); 
    } 

    public void doA(int p, int q, int r){ 
     // do something that requires x,y and p, q, r 
    } 

    public void doB(int q, int r, int s){ 
     // does something else that requires x, y and q, r, s 
    } 
} 

ora sembra qualcosa di simile:

public class Top_Level_Class(){ 
    int x, y; 
    SomeClass1a a = new SomeClass1a(); 
    SomeClass1a b = new SomeClass1b(); 
    // gets user input which changes x, y; 
    public void main(){ 
     int p, q, r, s; 
     // compute p, q, r, s 
     a.doA(p,q,r); 
     b.doB(q,r,s); 
    } 

public class SomeClass1a() { // in its own separate file 
    public void doA(int p, int q, int r){ 
     // do something that requires x,y and p, q, r 
    } 
} 


public class SomeClass1b() { // in its own separate file 
    public void doB(int q, int r, int s){ 
     // does something else that requires x, y and q, r, s 
    } 
} 

Quindi, comunque, dovrei passare xey ogni volta (dove x, y sono le variabili memorizzate nel func della classe helper)?

a.set(x,y); 
a.doA(p,q,r); 

La mia idea era di avere una classe contenitore speciale dove x e y sono trattenuti. La classe di primo livello dovrebbe avere un'istanza della classe contenitore e cambiare x, y utilizzando i metodi impostati.

// in the top level class: 
Container c = new Container(x,y); 
a.setContainer(c); 
b.setContainer(c); 

Le mie classi di helper avrebbero anche un'istanza del contenitore e farebbero riferimento alla stessa istanza del livello principale. In questo modo accedono alla stessa x, y del livello principale.

desidero sapere se devo

  • Utilizzare la classe contenitore
  • , y ogni volta carico x nelle sottoclassi
  • ?? Qualche metodo migliore ??
+3

La risposta qui è, purtroppo, "dipende". programmers.se potrebbe essere un obiettivo più fertile per questa domanda. – bmargulies

+0

Se la classe interna non è statica, può accedere anche ai membri della classe padre ... – Vojta

+0

Non è una classe interna se si trova in un file diverso. E non è una sottoclasse se non estende la superclasse. – Armand

risposta

10

Immagino che la risposta alla tua domanda sia il Pattern di progettazione chiamato Singleton. Fondamentalmente ti permette di ottenere e sfruttare la stessa (e unica) istanza di una classe ogni volta che vuoi nel tuo sistema.

Questa è la sua implementazione (si prega di perdonare eventuali errori di sintassi, non ho compilarlo):

class Container{ 

    //eventually provides setters and getters 
    public float x; 
    public float y; 
    //------------ 

    private static Container instance = null; 
    private void Container(){ 

    } 
    public static Container getInstance(){ 
    if(instance==null){ 
     instance = new Container(); 
     } 
     return instance; 
    } 
} 

se poi altrove nel codice si importa il contenitore è possibile scrivere ad esempio

Container.getInstance().x = 3; 
temp = Container.getInstance().x; 

e si influiranno sugli attributi dell'istanza contenitore univoca che si ha nel proprio sistema

In molti casi è comunque preferibile utilizzare la dipendenza Injec schema di riferimento in quanto riduce l'accoppiamento tra diversi componenti.

+0

Molto interessante. Ha una variabile statica di se stesso. Mi chiedo solo, come fa questa cosa a uscire dal campo di applicazione? Se è statico, non rimarrà in esistenza? O lo imposto su null quando ho finito con esso? – f20k

+0

Scusa ma non ho capito la tua domanda :(comunque la sua istanza è statica, una volta inizializzata, rimarrà in essere. Non devi, e non puoi, impostarla su null. Consideralo un repository condiviso delle tue variabili :) Comunque ecco una spiegazione del Pattern http: //en.wikipedia.org/wiki/Singleton_pattern – Sindico

+0

Hmm bene il Singleton avrà senso se ho solo bisogno di istanziarlo una volta. Tuttavia, la mia funzione di primo livello è in realtà una discussione che verrà istanziata/distrutta più volte durante l'esecuzione del programma. Beh suppongo di poter sovrascrivere i valori ogni volta. – f20k

0

Ho difficoltà a vedere qual è il tuo problema - perché non vuoi passare x un y come parametro?

Oh, bene. Supponendo che tu non lo faccia, non vedo la necessità di una nuova classe contenitore. Farlo in questo modo:

public class SubClass1a() { // in its own separate file 
    public void doA(Top_Level_Class caller, int p, int q, int r){ 
     // do something that requires x,y and p, q, r 
     // **to get x use the expression term caller.getX() and caller.getY()** 
    } 
} 

Naturalmente è necessario aggiungere i metodi getter pubblico GetX() e Gety() per Top_Level_Class.

Se non si desidera che SubClass1a dipenda da Top_Level_Class, è possibile creare un'interfaccia che consenta l'accesso alle variabili.

+0

Hmm ok. Dovrò dare un'occhiata alle interfacce di più. Il motivo principale per cui non volevo passare x, y ogni volta è perché ho diverse funzioni in diverse sottocategorie che uso ciascuna (x, y, z, ecc.) E non sembrava giusto passare come 6-8 variabili ciascuna ora chiamo una funzione. Le sottoclassi erano dipendenti, ma sto cercando di estrarle dal file in modo che possano essere utilizzate in un progetto diverso. – f20k

+1

@ f20k Il tuo istinto di non voler passare 6-8 parametri a un metodo è sulla strada giusta. Le liste di parametri che sono lunghe indicano che dovresti considerare di raggruppare questi parametri in un oggetto o 2. – dhable

+0

@Dan, grazie per il tuo suggerimento. Penso che implementerò un contenitore. Ha molto senso. Ero solo preoccupato che sarebbe stata una cattiva pratica di programmazione se avessi condiviso i dati in questo modo. – f20k

0

Blockquote Il motivo principale non volevo passare x, y ogni volta che è perché ho diverse funzioni in diverse sottoclassi che ogni utilizzo (x, y, z, ecc) e che non ha ancora sembra giusto passare come 6-8 variabili ogni volta che chiamo una funzione. Le sottoclassi erano dipendenti, ma sto cercando di estrarle dal file in modo che possano essere utilizzate in un progetto diverso. Blockquote

Se questo è il caso, allora è meglio astrarre le variabili in una classe contenitore. Se ogni istanza di queste classi non più dipendenti utilizzerà un grosso sottoinsieme di queste variabili, allora ha senso averle tutte in un'unica istanza. Le variabili che sono correlate logicamente dovrebbero essere trovate nello stesso posto.Il tuo approccio dovrebbe essere qualcosa di simile:

public class Top_Level_Class(){ 
Container container = new Container(x, y, p, q, r, s); 
SubClass1a a = new SubClass1a(container); 
SubClass1a b = new SubClass1b(container); 
// gets user input which changes x, y using container's getters and setters 
public void main(){ 
    // compute and set p, q, r, s 
    a.doA(); 
    b.doB(); 
} 

public class SubClass1a(Container c) { // in its own separate file 
    public void doA(c.getX, c.getY, c.getP, c.getQ, c.getR){ 
     // do something that requires x, y, p, q, and r 
    } 
} 

public class SubClass1b(Container c) { // in its own separate file 

    public void doB(c.getX, c.getY, c.getQ, c.getR, c.getS){ 
     // does something else that requires x, y, q, r, and s 
    } 
} 

public class Container(x, y, p, q, r, s) { 
    //getters and setters for all variables 
} 

Questo ti impedisce di entrare in una situazione di spaghetti-codice variabile che passa, e quando si desidera utilizzare solo uno o due di queste classi in seguito, il codice è modulare abbastanza da port con solo quelle classi e il tuo contenitore.

+0

Questa sintassi è errata e sembra più complicata del suggerimento originale. – Armand

0

Questa domanda è un po 'folle - il codice nella domanda non verrà compilato.

public class Main { 
    public static void main(String... args) { 
     MutableDataContainer m = new MutableDataContainer(); 
     ImmutableDataContainer i = computeImmutableData(); 
     new ADoer().doA(m, i); 
     new BDoer().doB(m, i); 
    } 
    ... 
} 

class MutableDataContainer { 
    private int x, y; 
    ... // getters and setters below 
} 

class ImmutableDataContainer { 
    private final int p, q, r, s; 
    ... // getters below 
} 

Sarà necessario definire ADoer e BDoer pure.

+0

Spiacente, il codice che ho scritto lì è di aiutare a dare un'idea di quello che voglio fare. In realtà non funziona. Il codice effettivo è in realtà piuttosto complicato con 100+ linee. In pratica sto provando a condividere alcune variabili molto spesso utilizzate in top_level_class tra le classi helper in file separati. La domanda è quale metodo sarebbe il migliore - efficiente-saggio e perfetto per il mondo – f20k

Problemi correlati