2010-11-02 22 views
20

Antes que nada, por favor, perdóneme si es una pregunta realmente tonta, solo estoy tratando de aprender este idioma hasta su núcleo. Estoy leyendo Java efectivo y el primer capítulo habla sobre métodos de fábrica estáticos frente a constructores. Sus pros y contras. Algunas cosas que son confuso para mí son:método de fábrica estático público

  1. clase de un objeto devuelto por el método de fábrica estática es no pública - lo que significa exactamente?
  2. a diferencia de los constructores métodos de fábrica estáticos no son necesarios para crear un nuevo objeto cada vez que se invocan - ¿Cómo sucede esto? Invoco el método de fábrica solo para obtener un nuevo objeto y, ¿comprobamos si el objeto ya existe?

Gracias.

+2

+1 para profundizar en la práctica del diseño de software y hacer una buena pregunta. –

+0

Gracias Brian :) – t0mcat

+0

+1 por preguntar POR QUÉ, en lugar de simplemente hacer la programación por escrito. Hábito de un buen codificador. – TreyE

Respuesta

11

la clase de un objeto devuelto por el método de fábrica estático no es pública - ¿qué significa exactamente?

Significa que la clase real de los objetos devueltos por un método de fábrica estático puede ser una subclase del tipo declarado, y esta subclase no tiene que ser pública. Es solo otro detalle de implementación que el código del cliente no debería importar.

a diferencia de los constructores métodos de fábrica estáticos no son necesarios para crear un nuevo objeto cada> vez que se invocan - ¿Cómo sucede esto? Invoco el método de fábrica solo para obtener un nuevo objeto y, ¿comprobamos si el objeto ya existe?

Sí, esa es una forma en que esto podría hacerse. Pero realmente, todo es posible.

+0

Hola Micheal, ¿entonces depende de los requisitos? No hay una regla rígida que los métodos de fábrica siempre deben verificar si hay una instancia ya presente. – t0mcat

+0

@ t3ch: Sí, absolutamente. El punto es que puedes hacer eso con métodos de fábrica si es útil y qué quieres hacer ... no tienes esa opción con 'nuevo'. – ColinD

+0

wow gracias. Al menos ahora sé dónde sería útil. Singletons se puede entender mejor con este enfoque. – t0mcat

2

Cuando usa la palabra clave new, usted como desarrollador sabe que el JDK creará una nueva instancia de ese objeto. Lo que dice el autor, cuando usas un método estático, el desarrollador ya no sabe si el método está creando una nueva instancia o posiblemente haciendo otra cosa. Algo más puede ser reutilizar datos en caché, agrupación de objetos, crear una implementación privada y devolver una subclase de la clase.

+0

>> si el método está creando una nueva instancia o posiblemente haciendo otra cosa. Amir, si el método estático no está creando una nueva instancia o devolviendo un nuevo objeto, entonces ¿por qué necesitamos un método de fábrica estático? – t0mcat

+2

Es posible que no siempre necesite una nueva instancia de algo. Tomemos, por ejemplo, las conexiones a la base de datos: lo hace en java jdbc.newConnection(). Pero java no crea una nueva instancia cada vez. Primero verifica si ya existe una conexión. Si no, obtendrá una nueva instancia. Otro ejemplo podría ser que desea crear un singleton. (Los Singleton tienen su propio problema) Lo que significa que hay una buena lectura de por qué debería haber solo una instancia de una clase. Así que de nuevo harías tu constructor privado y solo permitirías que tu API se use a través de clases estáticas. –

+0

¡Además, no estoy diciendo que los métodos de fábrica estáticos sean buenos en todos modos! Solo digo que a veces lo necesitas, pero solo úsalo si es necesario. Debe ser más limpio usar constructores que algún método confuso que el desarrollador tenga que buscar. –

1

clase de un objeto devuelto por método de fábrica estática es no pública

frecuentes un método de fábrica estática volverá o bien un un objeto escrito como una interfaz (más común), o, a veces algunos clase base (menos común). En cualquier caso, no conoce la clase exacta del objeto devuelto.

La ventaja de esto es obtener un objeto cuyo comportamiento conozca sin preocuparse por los detalles desordenados de la clase que crea.

a diferencia de los constructores no son necesarios métodos de fábrica estáticos para crear un nuevo objeto cada vez que se invocan

Para entender esto, consideremos el caso de trabajar con un conjunto unitario. Puede llamar .getInstance() en algunas clases de fábrica para obtener la instancia única de un determinado objeto.Normalmente, lo que hace es crear una instancia del objeto si aún no existe, o darle la instancia existente si ya existe. En cualquier caso, recuperas una copia del objeto. Pero usted no (y no) sabrá si este singleton tuvo que ser creado, o si uno ya había sido construido previamente.

La ventaja de esto es que el ciclo de vida del objeto y cuando se crea se gestiona para usted.

+0

Hola Trey, Tu ejemplo único realmente despejó mi duda. Gracias :) – t0mcat

0

Ambas preguntas se pueden responder mirando algún código que haga uso de estas dos propiedades de los métodos estáticos de fábrica. Sugiero mirar en Guava ImmutableList.

Observe cómo el método de fábrica no-arg of() siempre devuelve la misma instancia (no crea una nueva instancia cada vez). Si observa detenidamente, también notará que su método de fábrica copyOf(Iterable) realmente devuelve el objeto que se le pasa si ese objeto es en sí mismo un ImmutableList. Ambos están aprovechando el hecho de que un ImmutableList garantiza que nunca cambiará.

Nótese también cómo diversos métodos de fábrica en la devuelven diferentes subclases, tales como , SingletonImmutableList y RegularImmutableList, sin exponer los tipos de esos objetos. Las firmas de método solo muestran que devuelven ImmutableList, y todas las subclases de ImmutableList tienen visibilidad de paquete privado (por defecto), haciéndolas invisibles para los usuarios de la biblioteca. Esto ofrece todas las ventajas de múltiples clases de implementación sin agregar complejidad desde la perspectiva del usuario, ya que solo se les permite ver ImmutableList como un solo tipo.

Además de ImmutableList, la mayoría de las clases instanciables en Guava utilizan métodos estáticos de fábrica. Guava también ejemplifica muchos de los principios establecidos en Java efectivo (lo que no sorprende, dado que fue diseñado por esos principios y con la guía del propio Josh Bloch), por lo que puede ser útil echarle un vistazo más a medida que ' re trabajando a través del libro.

+0

Gracias por el ejemplo de Colin. Pasando por eso. – t0mcat

4

En primer lugar, felicitaciones a su elección en Java-lit: libro de Bloch es un excelente primer.

Para responder a su segunda pregunta ('a diferencia de los constructores, los métodos de fábrica estáticos no son necesarios para crear un objeto nuevo cada vez que se invocan'), es importante darse cuenta de que lo que Bloch dice es que con una fábrica estática la opción de cualquiera de los dos: devolver un nuevo objeto o devolver uno preexistente. Todo depende de lo que quieras hacer.

Por ejemplo, supongamos que tiene una clase de valor realmente simple de tipo Dinero. Su método de fábrica estático probablemente debería devolver una nueva instancia, es decir, un nuevo objeto con un valor específico para Money. Así, de esta manera:

public class Money { 

    private Money(String amount) { ... } /* Note the 'private'-constructor */ 

    public static Money newInstance(String amount) { 
     return new Money(amount); 
    } 

} 

Pero digamos que usted tiene algún objeto que administra algún recurso y desea sincronizar el acceso a ese recurso a través de alguna clase ResourceManager. En ese caso, probablemente desee que su método de fábrica estático devuelva la misma instancia a todas las personas, lo que obligará a todos a pasar por la misma instancia, para que esa instancia 1 pueda controlar el proceso. Esto sigue el patrón singleton. Algo como esto:

public ResourceManager { 

    private final static ResourceManager me = new ResourceManager(); 

    private ResourceManager() { ... } /* Note the 'private'-constructor */ 

    public static ResourceManager getSingleton() { 
     return ResourceManager.me; 
    } 
} 

El método anterior obliga al usuario a sólo alguna vez ser capaz de utilizar una única instancia, lo que le permite controlar con precisión quién (y cuándo) tiene acceso a lo que sea que está administrando.


Para responder a su primera pregunta, considere esto (aunque no es el mejor ejemplo, es bastante ad-hoc):

public class Money { 

    private Money(String amount) { ... } 


    public static Money getLocalizedMoney(MoneyType localizedMoneyType, String amount) { 
     switch(localizedMoneyType) { 
      case MoneyType.US: 
       return new Money_US(amount); 
      case MoneyType.BR: 
       return new Money_BR(amount); 
      default: 
       return new Money_US(amount); 
     } 
    } 
} 

public class Money_US extends Money { ... } 

public class Money_BR extends Money { ... } 

Nota cómo puedo ahora hacer esto:

Money money = Money.getLocalizedMoney(user_selected_money_type); 
saveLocalizedMoney(money); 

Una vez más, un ejemplo realmente artificial, pero ojalá te ayude a ver más o menos a lo que estaba llegando Bloch con ese punto.

Las otras respuestas fueron buenas, creo que, como principiante, a veces es útil ver un código real.

+0

> simplemente piense que, como principiante, a veces ayuda ver un código real. Gracias por considerar este hecho Bane. Sus ejemplos son realmente útiles, especialmente aquel en el que está creando una instancia privada y devolviendo la misma instancia cada vez para ResourceManager. – t0mcat

+0

np - cada vez que aprendo un nuevo concepto, siempre lucho con respuestas abstractas/vagas, el código difícil junto con una breve explicación generalmente va mucho más allá. Por cierto, "Artículo 3" en el libro de Bloch le dará mucho más para masticar sobre el enfoque de fábrica singleton. – Bane

+0

Gracias Bane. deseando que llegue. Ustedes van a ver toneladas de preguntas de mi :) – t0mcat

Cuestiones relacionadas