Come implementare Singleton su un caso Resource / ResourcesManager?

2

Questo è un esercizio di domanda accademica modello di progettazione. Abbiamo una classe di risorse e una pura classe di produzione ResourcesManager per gestire gli oggetti con tipo di risorsa.

La domanda è Date le seguenti due definizioni:

public class Resource {

}

public class ResourcesManager {

 public static Resource loadFromDb(int resID) {
   ...
 }
 public static Resource createNew(String name) {
    ...
 }
}

Applica modello Singleton e Factory

La mia soluzione sarebbe quella di applicare Singleton e Factory sia alla classe ResourcesManager. Dal momento che ho bisogno di una sola istanza di Manager, ed è quella responsabile della creazione di nuovi oggetti.

Alcuni altri studenti dall'altra parte vogliono applicare la classe Singleton alla classe di risorse .....

Ma se penso all'esecuzione seguente su un possibile cliente:

Resource r1 ResourcesManager = ResourcesManager.loadFromDb (1); Resource r2 ResourcesManager = ResourcesManager.loadFromDb (2);

Avrò il comportamento imprevisto che r1 = r2 .... Perché si riferiscono alla stessa istanza di risorsa Singleton ....

Questa è la soluzione che ho in mente:

public class Resource {
     private String nome ;
     private int id;

     public Resource(){}

public void setName(String n){
    name=n;
}

public void setID(int n){
    id=n;
}

public String getName(){
     return name;
}

public int getID(){
     return id;
}

}



public class ResourcesManager {
  private static final ResourcesManager theInstance = new ResourcesManager();
  private ResourcesManager(){ }

  public static ResourcesManager getInstance(){
       return theInstance;
  }

  public static Resource loadFromDb(int resID) {
    Class.classForName(“Driver”);
    Connection con=DriverManager.get.Connection(...);
    Statement sta = con.createStatement();
    ResultSet rs = sta.executeQuery(“select name from resources where id=”+resID);
    if (rs.next){
              String name=rs.getString(“name”);
    }

    Resource s = new Resource();
    s.setName(name);
    s.setID(resID);
    return s; 
  }
  public static Resource createNew(String name) {
    Resource s = new Resource();
    s.setName(name);
    return s;
  }
}
    
posta koalaok 09.01.2016 - 11:32
fonte

1 risposta

2

This is a design pattern academic question exercise

Va bene, in questo caso tralascio lo standard "probabilmente non dovresti usare il saggio"!

My solution would be to apply Singleton and Factory both to ResourcesManager class. Since I need only one instance of the Manager, and it's the one in charge of creating new objects.

Some other student on the other side want to apply the Singleton to the Resource class.....

Bene, hai ragione e hanno torto. Una risorsa non è minimamente appropriata per un singleton, proprio per le ragioni che dici. Infatti sembra che tu sappia già la maggior parte di questo, ma elenciamo esplicitamente tutti i motivi:

  • Concettualmente, puoi avere più risorse differenti nel tuo sistema. Cercando di modellare quel concetto con una classe che puoi avere solo di uno non ha senso.
  • Praticamente, probabilmente do vuoi essere in grado di avere più risorse contemporaneamente in memoria. Non c'è nulla nel codice o nella domanda che ti suggerisca di poter escludere uno scenario così fondamentale.
  • Se lo facessi, otterrai il bizzarro comportamento che il caricamento di una nuova risorsa cambierebbe in uno già esistente in un modo molto inaspettato. Ciò accoppiasse orribilmente ogni pezzo di codice che voleva usare una risorsa, probabilmente portando a codice "big ball of mud", bug e mancanza di testabilità.
  • Dovendo essere in grado di aggiornare la risorsa significa che dovresti rendere i suoi campi mutabili, cosa che di solito vuoi evitare.
  • La domanda ti sta chiaramente suggerendo di avere una risorsa restituita da ResourceManager. Se il suo comportamento consisteva semplicemente nell'aggiornamento della risorsa esistente, sarebbe void e dovresti accedere alla singola Risorsa come singleton.
  • Allo stesso modo, la denominazione dei metodi nella domanda. createNew mi legge come se chiunque avesse scritto la domanda urlando nella pagina "Non usare un singleton per questo!" Un metodo chiamato crea nuovo non dovrebbe aggiornare esistente
  • Non c'è assolutamente alcun motivo per pensare che la memoria che potresti salvare dalla soluzione singleton sia singolare.

In effetti, espandendo su quest'ultimo punto, è davvero improbabile che tu abbia intenzione di risparmiare memoria dalla soluzione singleton in primo luogo. Esistono tre possibili scenari:

  • Usi sempre una sola risorsa. In questo caso, entrambe le soluzioni avranno le stesse prestazioni, creano un oggetto Risorsa.
  • Hai bisogno di più risorse differenti in memoria contemporaneamente (ad esempio, memorizzate in una raccolta). In questo caso, la tua soluzione è l'unica che funziona affatto.
  • Utilizzi più risorse diverse, ma solo una alla volta. In questo caso, è discutibile se alla fine avresti mai più oggetti di memoria in memoria. È probabile che nel momento in cui crei il secondo, il primo sarà andato fuori ambito e sarà stato raccolto.

    E infatti per la possibilità che la differenza di prestazioni sia significativa, dovresti usare un gran numero di risorse diverse, ma solo una alla volta, ma anche farlo in modo che quelle hai finito con non andare fuori portata, stai caricando i nuovi. Questa è una situazione veramente oscura e facilmente risolta, e anche allora , è probabile che l'overhead della memoria non sia importante. Quindi è una ragione estremamente debole su cui basare una decisione.

Come nota più generale, occasionalmente capita che devi seguire un design meno espressivo che non modella il dominio del problema anche per motivi di prestazioni. Se pensi di essere in questa situazione, ci sono due cose che dovresti fare:

  • Resistilo! In realtà è piuttosto raro che ciò accada, quindi chiediti un diverso, buon design che soddisfi le tue esigenze in termini di prestazioni.
  • Isolarlo. Se hai bisogno di qualcosa di brutto da qualche parte, prova a contenerlo in modo che solo una piccola quantità di altro codice debba occuparsi direttamente di quella bruttezza. Un singleton è esattamente l'opposto - per definizione è a livello di sistema! Se hai veramente scoperto che la creazione di più risorse era un problema, sarebbe una soluzione migliore e più isolata da modificare o aggiungere all'interfaccia di ResourcesManager :

    public class ResourcesManager {
    
         public static void populateFromDb(Resource resource, int resID) {
           ...
         }
    
         public static void reset(Resource resource, String name) {
            ...
         }
    }
    
risposta data 09.01.2016 - 12:20
fonte

Leggi altre domande sui tag