2010-11-16 12 views
13

estoy familiarizado con la idea y los beneficios de un método de fábrica estática, como se describe en Effective Java de Joshua Bloch:Caso de uso realista para el método de fábrica estático?

  • métodos de fábrica tienen nombres, para que pueda tener más de un método de fábrica con la misma firma, a diferencia constructores
  • Los métodos de fábrica no tienen que crear un objeto nuevo; pueden devolver un objeto creado previamente. Esto es bueno para objetos inmutables u objetos de valor.
  • Los métodos de fábrica pueden devolver un objeto de cualquier subtipo de su tipo de devolución, a diferencia de los constructores.

Ahora estoy tratando de explicar los métodos de fábrica estáticos para alguien que está aprendiendo los principios de Java y OO. Aprende mejor de escenarios concretos en lugar de abstracciones. Si ella puede ver el patrón en el trabajo, resolviendo algún problema, lo obtendrá. Pero le resulta más difícil leer una lista abstracta de características como la anterior para comprender cómo aplicar el patrón.

¿Puede ayudarme a encontrar un ejemplo realista del uso de un método de fábrica estático, que aclara sus ventajas, pero que todavía es lo suficientemente simple como para mostrar a alguien en una clase introductoria de Java?

Esta persona tiene experiencia en programación en PL/SQL pero nunca aprendió a aprender patrones de programación orientada a objetos.

+0

¿Has marcado esta opción? http://stackoverflow.com/questions/929021/what-are-static-factory-methods-in-java –

Respuesta

15

Utilice javax.swing.BorderFactory como un ejemplo de los tres puntos.

Esta clase se utiliza para hacer bordes para objetos columpios. Estos objetos fronterizos se pueden reutilizar fácilmente, y este método de fábrica lo permite. Aquí está the javadoc. Esta fábrica es un gran ejemplo de los tres puntos:

  • Existen múltiples métodos estáticos con diferentes nombres como createEmptyBorder() y createEtchedBorder().
  • Estos métodos devolverán objetos creados previamente cuando sea posible. Es bastante frecuente que se use el mismo borde en una aplicación.
  • Border es en realidad una interfaz, por lo que todos los objetos creados a través de esta fábrica son en realidad clases que implementan esta interfaz.
+1

Este es un gran ejemplo. –

+0

@Erick Me gustó tu ejemplo. Pero el libro también implica esta aplicación: una aplicación de esta flexibilidad es que una API puede devolver objetos sin haciendo que sus clases sean públicas. Pero en tu caso de ejemplo, todas las clases son públicas. Entonces, ¿hay algún ejemplo que cubra esta aplicación también? – dosdebug

4

El ejemplo de libro de su segundo punto es Integer.valueOf(int) (similar para Boolean, Short, Long, Byte). Para los valores de parámetro -128 a 127, este método devuelve una instancia en caché en lugar de crear un nuevo Integer. Esto hace (auto) boxeo/unboxing mucho más eficiente para valores típicos.

No se puede hacer eso con new Integer() ya que el JLS requiere que new crear una nueva instancia cada vez que se llama.

3

¿No sería bueno Calendar.getInstance() ser un buen ejemplo? Crea según el lugar un calendario budista, un calendario imperial japonés o, por defecto, un calendario gregoriano.

+0

-1 Esta no es una respuesta, es una pregunta. –

0

Aquí hay uno que tuve que hacer hace un tiempo. En una entrevista de trabajo, me pidieron que programara un mazo de cartas donde se pueden barajar. Problema realmente simple.Creé:

Card: 
    suit 
    rank 

Deck: 
    card[] 

Creo que el factor distintivo es que solo puede haber 52 tarjetas en todo momento. Así que hice que el constructor de Card() fuera privado y, en su lugar, creé el valor de fábrica estático de (suit, rank) Esto me permitió almacenar en caché las 52 cartas y convertir lo inmutable. Enseñó muchas lecciones básicas importantes en esos libros.

  1. inmutable
  2. creación de control de objeto
  3. métodos estáticos
  4. posiblemente subclases y devolver una tarjeta de otra fuente. (No hice esto)

Esto es similar a Boolean y Byte, excepto que utilicé un ejemplo de tarea común para mostrar por qué es importante controlar las instancias. También creé una función de ayuda para la plataforma llamada newDeck() porque quería mostrar una instancia en la que el constructor no necesitara ser privado, pero aún así sería bueno tener una fábrica estática auxiliar.

Espero que esto ayude!

+0

Con este ejemplo en particular, podría incluso buscar una enumeración, ya que es conocido en tiempo de compilación cada instancia de su clase que alguna vez se puede crear. –

+0

¡De hecho hice una enumeración! Hice dos, tres, cuatro ... Jack, Queen, King y As. También creé corazones, palos, picas y diamantes. Esto funcionó perfectamente porque todo estaba comprobado estáticamente en tiempo de compilación y mis parámetros para valueOf (Rango de rango, Traje de palo). Muy simple pero aún enseña mucho acerca de la programación OO. –

0

El caso simple. Supongamos que tiene una clase que opera algún tipo de impresora, pero no importa si es epson, canon u otra cosa. Entonces, simplemente crea una interfaz Printer, crea algunas implementaciones y crea una clase que solo tiene un método: createPrinter.

Por lo tanto, el código será simple: Código

public interface Printer { 
     print(); 
    } 

    class CanonPrinter implements Printer { 
     print() { 
    // ... 
     } 
    } 


    public PrinterFactory { 

    Printer createPrinter() { 
    if (...) { 
     return new CanonPrinter(); 
    } else { 
     return new EpsonPrinter(); 
    } 
} 
} 

cliente:

Printer printer = PrinterFactory.createPrinter(); 
printer.print(); 

Aquí abstracta que Clinet código de ningún detalle de lo que impresoras que puede operar con o cómo manejan la impresión . A PrinterFactory le importa qué impresora elegir si, por ejemplo, funciona mal.

4

Mi ejemplo favorito actual de este patrón es Guava 's ImmutableList. Las instancias de este solo pueden ser creadas por fábricas estáticas o un constructor. Aquí hay algunas maneras de que esto es ventajoso:

  • Desde ImmutableList no expone ningún publicprotected o constructores, puede tener subclases dentro del paquete mientras que no permite a los usuarios subclase (y potencialmente rompen su garantía inmutabilidad).
  • Dado que, sus métodos de fábrica son capaces de devolver subclases especializadas sin exponer sus tipos.
  • Su método de fábrica ImmutableList.of() devuelve una instancia única de . Esto demuestra cómo un método de fábrica estático no necesita crear una nueva instancia si no es necesario.
  • Su método ImmutableList.of(E) devuelve una instancia de SingletonImmutableList que está optimizada porque solo tendrá exactamente 1 elemento.
  • La mayoría de sus otros métodos de fábrica devuelven RegularImmutableList.
  • Su método de fábrica estático copyOf(Collection) tampoco siempre necesita crear una nueva instancia ... si el Collection que se da es un ImmutableList, ¡simplemente puede devolver eso!
+0

Bien, morderé. ¿Exactamente qué haría uno con una lista vacía inmutable? –

+2

@Chris: Lo mismo que se hace con, digamos, 'Collections.emptyList()' (que también es un singleton inmutable). Cuando un método que devuelve una 'Lista 'no tiene ningún dato que devolver, siempre debe devolver una' Lista' vacía en lugar de 'null'. Como una colección vacía e inmutable nunca puede contener ningún dato, una instancia única se puede usar en cualquier lugar que se necesite. Además, esa instancia puede ser tan liviana como sea posible ya que ni siquiera necesita estructuras de datos internas para contener nada. – ColinD

Cuestiones relacionadas