2009-08-25 3 views
15

Recentemente ho affrontato una domanda: Come evitare di creare un'istanza di una classe Java?Evitare l'istanziazione di una classe in java

Tuttavia, ho risposto dicendo:

  1. Se non si desidera creare un'istanza di una classe, usa il modificatore "astratto". Es: javax.servlet.HttpServlet, è dichiarato come astratto (sebbene nessuno dei suoi metodi sia astratto) per evitare l'istanziazione.

  2. Dichiarare un costruttore privato senza argomenti.

Ora la mia domanda è a) ci sono altri modi? b) perché qualcuno non vuole istanziare una classe? - dopo aver cercato in SO, ho saputo dallo this che le classi Util possono essere fatte per non istanziare. In altri posti in cui non vogliamo creare un'istanza di una classe in OOP?

risposta

24

quattro ragioni in mente:

  1. Per consentire sottoclassi, ma non il genitore per essere istanziati;
  2. Per non consentire l'istanziazione diretta e fornire invece un metodo di fabbrica per restituire e, se necessario, creare istanze;
  3. Poiché tutte le istanze sono predefinite (ad esempio, le mute in un mazzo di carte) sebbene, dal momento che a partire da Java 5, si consigliano invece le enumerazioni di tipo typesafe; e
  4. La classe in realtà non è una classe. È solo un supporto per costanti e/o metodi statici.

Come esempio di (2), è possibile creare oggetti canonici. Ad esempio, combinazioni di colori RGB. Se non si desidera creare più istanze di qualsiasi combinazione RGB in modo da fare questo:

public class MyColor { 
    private final int red, green, blue; 

    private MyColor(int red, int green, int blue) { 
    this.red = red; 
    this.green = green; 
    this.blue = blue; 
    } 

    public static MyColor getInstance(int red, int green, int blue) { 
    // if combo already exists, return it, otherwise create new instance 
    } 
} 

Nota: è necessario costruttore no no-arg perché un altro costruttore è esplicitamente definito.

2

Penso che il motivo più comune per non voler istanziare una classe è quando si ha a che fare con una classe statica, e quindi con i suoi metodi statici. Non vuoi che qualcuno provi a istanziare quella classe. Allo stesso modo, quando si hanno a che fare con classi Factory o in alcuni casi molte classi singleton nasconderanno il loro costruttore per non essere istanziate nel modo normale.

3

A volte si desidera evitare solo altri istanziazione degli oggetti, in modo da avere il pieno controllo su tutte le istanze esistenti. Un esempio è lo singleton pattern.

1

Un altro modo per rendere una classe non-instantiable sarebbe dichiararlo come una classe interna privata, e quindi non fornire alcun modo per istanziarlo nella classe circostante. Ma questo è (IMO) piuttosto inutile.

Vuoi che una classe sia non-istantanea se non ha senso istanziarla. In genere lo fai se la classe è in realtà solo una raccolta di metodi helper (statici) o se la classe è "incompleta". L'incompletezza può essere sintatticamente ovvia (cioè i metodi astratti), ma esistono altri tipi di incompletezza.Ad esempio, potresti fornire implementazioni predefinite di default per tutti i metodi e richiedere che uno o più di essi vengano sovrascritti affinché la classe faccia qualcosa di utile.

Un altro motivo per rendere una classe non-instantiable (o almeno non direttamente istanziabile) è se l'applicazione deve controllare l'istanza. Ad esempio, la classe java.util.regex.Pattern non può essere istanziata direttamente in modo che JRE possa (potrebbe) mantenere una cache di espressioni regolari precompilate.

8

Non proprio una risposta alla tua domanda, ma solo una nota:

Quando si effettua un costruttore privato no-arg per evitare di istanze delle classi di utilità, si dovrebbe avere il costruttore un'eccezione (ad esempio UnsupportedOperationException). Questo perché puoi effettivamente accedere ai membri privati ​​(compresi i costruttori) attraverso la riflessione. Nota che se lo fai, dovresti accompagnarlo con un commento, perché è un po 'contro-intuitivo che tu definisca un costruttore su impedendo che una classe venga istanziata.

Rendere l'abstract della classe di utilità non è una buona idea perché rende la classe simile a come è intesa per essere estesa e inoltre è possibile estendere la classe e quindi istanziarla.