2009-09-15 10 views
5

¿Puede una clase devolver un objeto en sí misma?¿Puede una clase devolver un objeto en sí misma?

En mi ejemplo, tengo una clase llamada "Cambiar" que representa un cambio en el sistema, y ​​me pregunto si está de todos modos en contra de los principios de diseño devolver un objeto de tipo Change o ArrayList que se rellena con todos los objetos Change recientes.

Respuesta

3

Sí, puede. De hecho, eso es exactamente lo que hace una clase singleton. La primera vez que llame a su método de nivel de clase getInstance(), construye una instancia de sí mismo y lo devuelve. Luego, las llamadas subsiguientes al getInstance() devuelven la instancia ya construida.

Su caso particular podría utilizar un método similar pero necesita alguna forma de decidir la lista de cambios recientes. Como tal, deberá mantener su propia lista de dichos cambios. Puede hacer esto con una matriz estática o una lista de los cambios. Solo asegúrese de que la información subyacente en la lista no desaparezca; esto podría suceder en C++ (por ejemplo) si mantiene punteros a los objetos y esos objetos fueron liberados por sus clientes.

Un problema menor en un entorno de recolección de basura automática como Java, ya que el objeto no desaparecería mientras aún hubiera una referencia al mismo.

Sin embargo, usted no tiene tiene para utilizar este método. Mi preferencia con lo que describes sería tener dos clases, una lista de cambios y un cambio. Cuando crea una instancia de la clase de cambio, pase un objeto de lista de cambios (nulo si no lo quiere asociado a una lista de cambios) con el constructor y agregue el cambio a esa lista antes de devolverlo.

Alternativamente, tenga un método de lista de cambios que cree un cambio y lo devuelva, recordando el cambio para sus propios fines.

Luego puede consultar la lista de cambios para obtener los cambios recientes (como quiera que los defina). Eso sería más flexible ya que permite múltiples listas.

Incluso podría excederse y permitir que un cambio se asocie con múltiples listas de cambios si así lo desea.

+1

Busco singleton en Google, parece que un singleton es un objeto único que mantiene el estado del sistema. En mi caso, habrá muchos de estos objetos de "Cambio" en un momento dado que representen cambios recientes. ¿Hay un nombre para tal patrón? – Ankur

+0

Ver mi actualización sobre cómo lo diseñaría (una lista de cambios por separado y una clase de cambio). De la forma en que lo tiene, cada cambio tiene conocimiento de cualquier otro cambio, lo que parece estirar los límites de la encapsulación demasiado para mi gusto. Por supuesto, hazlo si te sientes cómodo, pero yo no lo haría. – paxdiablo

+0

Sí, me gusta la idea de la clase ChangeList. Gracias – Ankur

0

No conozco ninguna regla de diseño que diga que eso sea malo. Entonces, si en su modelo, un solo cambio puede estar compuesto por múltiples cambios, puede hacerlo.

3

Una clase a menudo devolverá una instancia de sí mismo de lo que a veces se llama un método de "fábrica". En Java o C++ (etc.), esto normalmente sería un método público estático, p. lo llamarías directamente en la clase y no en una instancia de una clase.

En su caso, en Java, podría ser algo como esto:

List<Change> changes = Change.getRecentChanges(); 

Esto supone que la propia clase Cambio sabe cómo controlar los cambios en sí, en lugar de que el trabajo bajo la responsabilidad de algún otro objeto en el sistema.

Una clase también puede devolver una instancia de sí mismo en el patrón Singleton, en la que desea asegurarse de que sólo una instancia de una clase existe en el mundo:

Foo foo = Foo.getInstance(); 
+0

¿Habría un problema si lo llamara desde una instancia de la clase en lugar de la clase en sí – Ankur

+0

No habría un problema per se, pero si se usa un cambio para modelar un cambio único (lo que sea que sea) al sistema, entonces parece sorprendente que ese cambio también sepa sobre muchos otros cambios. Es por eso que normalmente lo convertirías en un método estático de Cambio, donde tiene sentido tener más inteligencia global de lo que un solo Cambio conocería. –

+0

Sorprendido, esta es la única respuesta con la palabra "fábrica" ​​+1 – annakata

1

Los métodos de interfaz fluida trabajan en el principio de devolver una instancia de sí mismo, por ejemplo

StringBuilder sb = new StringBuilder("123"); 
sb.Append("456").Append("789"); 
2

Sí, una clase puede tener un método que devuelve una instancia de sí mismo. Este es un escenario bastante común.

En C#, un ejemplo podría ser:

public class Change 
{ 
    public int ChangeID { get; set; } 

    private Change(int changeId) 
    { 
     ChangeID = changeId; 
     LoadFromDatabase(); 
    } 

    private void LoadFromDatabase() 
    { 
     // TODO Perform Database load here. 
    } 

    public static Change GetChange(int changeId) 
    { 
     return new Change(changeId); 
    } 
} 
1

Es necesario pensar acerca de lo que está tratando de modelar. En su caso, tendría una clase ChangeList que contiene uno o más objetos Change.

Por otro lado, si estaba modelando una estructura jerárquica donde una clase puede hacer referencia a otras instancias de la clase, entonces lo que está haciendo tiene sentido. P.ej. un nodo de árbol, que puede contener otros nodos de árbol.

Otro escenario común es hacer que la clase implemente un método estático que devuelve una instancia de este. Eso debería usarse cuando se crea una nueva instancia de la clase.

5

Otra razón para volver this es por lo que se puede hacer la función de encadenamiento:

class foo 
{ 
    private int x; 
    public foo() 
    { 
     this.x = 0; 
    } 

    public foo Add(int a) 
    { 
     this.x += a; 
     return this; 
    } 

    public foo Subtract(int a) 
    { 
     this.x -= a; 
     return this; 
    } 

    public int Value 
    { 
     get { return this.x; } 
    } 

    public static void Main() 
    { 
     foo f = new foo(); 
     f.Add(10).Add(20).Subtract(1); 
     System.Console.WriteLine(f.Value); 
    } 
} 
 
$ ./foo.exe 
29 

Hay un tiempo y un lugar para hacer el encadenamiento de la función, y no es "en cualquier momento y en todas partes." Pero, LINQ es un buen ejemplo de un lugar que enormemente se beneficia del encadenamiento de funciones.

Cuestiones relacionadas