java - una - ¿Cuáles son los métodos de fábrica estática?
metodos estáticos (14)
estático
Un miembro declarado con la palabra clave ''static''.
métodos de fábrica
Métodos que crean y devuelven nuevos objetos.
en java
El lenguaje de programación es relevante para el significado de ''estático'' pero no para la definición de ''fábrica''.
¿Qué es un método de "fábrica estática"?
- Tienen nombres, a diferencia de los constructores, que pueden aclarar el código.
- no es necesario crear un nuevo objeto en cada invocación: los objetos se pueden almacenar en caché y volver a usar, si es necesario.
- puede devolver un subtipo de su tipo de retorno, en particular, puede devolver un objeto cuya clase de implementación es desconocida para el llamante. Esta es una característica muy valiosa y ampliamente utilizada en muchos marcos que usan interfaces como el tipo de retorno de los métodos de fábrica estáticos.
¡NOTA! "El método estático de fábrica NO es el mismo que el patrón del Método de fábrica " (c) Java efectivo, Joshua Bloch.
Método de fábrica: "Defina una interfaz para crear un objeto, pero deje que las clases que implementan la interfaz decidan qué clase crear una instancia. El método de fábrica permite que una clase difiera la creación de instancias a las subclases" (c) GoF.
"El método de fábrica estático es simplemente un método estático que devuelve una instancia de una clase". (c) Java efectiva, Joshua Bloch. Generalmente este método está dentro de una clase particular.
La diferencia:
La idea clave del método de fábrica estática es obtener control sobre la creación de objetos y delegarlo del método estático al constructor. La decisión del objeto a crear es como en Abstract Factory hecha fuera del método (en el caso común, pero no siempre). Mientras que la idea clave (!) De Factory Method es delegar la decisión de qué instancia de clase crear dentro de Factory Method. Por ejemplo, la implementación clásica de Singleton es un caso especial de método estático de fábrica. Ejemplo de métodos de fábrica estáticos de uso común:
- valor de
- obtener Instancia
- nueva instancia
El patrón de método estático de fábrica es una forma de encapsular la creación de objetos. Sin un método de fábrica, simplemente llamaría directamente al constructor la clase: Foo x = new Foo()
. Con este patrón, en su lugar, llamaría al método de fábrica: Foo x = Foo.create()
. Los constructores están marcados como privados, por lo que no se pueden llamar, excepto desde dentro de la clase, y el método de fábrica se marca como static
para que pueda llamarse sin tener primero un objeto.
Hay algunas ventajas de este patrón. Una es que la fábrica puede elegir entre muchas subclases (o implementadores de una interfaz) y devolver eso. De esta manera, la persona que llama puede especificar el comportamiento deseado a través de parámetros, sin tener que conocer o comprender una jerarquía de clases potencialmente compleja.
Otra ventaja es, como han señalado Matthew y James, controlar el acceso a un recurso limitado, como las conexiones. Esta es una forma de implementar grupos de objetos reutilizables : en lugar de construir, usar y derribar un objeto, si la construcción y la destrucción son procesos costosos, podría tener más sentido construirlos una vez y reciclarlos. El método de fábrica puede devolver un objeto instanciado no utilizado existente, si tiene uno, o construir uno si el recuento de objetos está por debajo de algún umbral inferior, o lanzar una excepción o devolver un null
si está por encima del umbral superior.
Según el artículo en Wikipedia, varios métodos de fábrica también permiten diferentes interpretaciones de tipos de argumentos similares. Normalmente, el constructor tiene el mismo nombre que la clase, lo que significa que solo puede tener un constructor con una signature determinada. Las fábricas no están tan limitadas, lo que significa que puede tener dos métodos diferentes que aceptan los mismos tipos de argumentos:
Coordinate c = Coordinate.createFromCartesian(double x, double y)
y
Coordinate c = Coordinate.createFromPolar(double distance, double angle)
Esto también se puede usar para mejorar la legibilidad, como señala Rasmus.
La implementación de Java contiene las clases de utilidades java.util.Arrays y java.util.Collections, ambas contienen métodos de fábrica estáticos , ejemplos y cómo usarlos:
Arrays.asList("1","2","3")
Collections.synchronizedList(..), Collections.emptyList(), Collections.unmodifiableList(...)
(Solo algunos ejemplos pueden buscar javadocs para ver más ejemplos de métodos https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html )
También la clase java.lang.String tiene tales métodos de fábrica estáticos :
-
String.format(...), String.valueOf(..), String.copyValueOf(...)
La legibilidad se puede mejorar mediante métodos de fábrica estáticos:
Comparar
public class Foo{
public Foo(boolean withBar){
//...
}
}
//...
// What exactly does this mean?
Foo foo = new Foo(true);
// You have to lookup the documentation to be sure.
// Even if you remember that the boolean has something to do with a Bar
// you might not remember whether it specified withBar or withoutBar.
a
public class Foo{
public static Foo createWithBar(){
//...
}
public static Foo createWithoutBar(){
//...
}
}
// ...
// This is much easier to read!
Foo foo = Foo.createWithBar();
Pensé que añadiría algo de luz a este post sobre lo que sé. Utilizamos esta técnica ampliamente en nuestro recent android project
. En lugar de creating objects using new operator
, también puede usar un static method
para crear una instancia de una clase. Listado de código:
//instantiating a class using constructor
Vinoth vin = new Vinoth();
//instantiating the class using static method
Class Vinoth{
private Vinoth(){
}
// factory method to instantiate the class
public static Vinoth getInstance(){
if(someCondition)
return new Vinoth();
}
}
Los métodos estáticos admiten la creación condicional de objetos : cada vez que invoca un constructor, se creará un objeto, pero es posible que no desee hacerlo. Supongamos que solo desea comprobar alguna condición y, a continuación, desea crear un nuevo objeto. No creará una nueva instancia de Vinoth cada vez, a menos que se cumpla su condición.
Otro ejemplo tomado de Java efectiva .
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
Este método traduce un valor primitivo booleano en una referencia de objeto booleano. El Boolean.valueOf(boolean)
nos ilustra, nunca crea un objeto. La capacidad de static factory methods
para devolver el mismo objeto a partir de invocations
repetidas permite a las clases mantener un control estricto sobre las instancias existentes en cualquier momento.
Static factory methods
son que, a diferencia de los constructors
, pueden devolver un object
de cualquier subtype
de su tipo de retorno. Una aplicación de esta flexibilidad es que una API puede devolver objetos sin hacer públicas sus clases. Ocultar las clases de implementación de esta manera conduce a una API muy compacta.
Calendar.getInstance () es un gran ejemplo de lo anterior. Crea, dependiendo de la configuración regional, BuddhistCalendar
, JapaneseImperialCalendar
o, por defecto, un Georgian
.
Otro ejemplo que podría pensar es el Singleton pattern
, en el que hace que sus constructores sean privados cree un método propio de getInstance
en el que se asegura de que siempre hay una sola instancia disponible.
public class Singleton{
//initailzed during class loading
private static final Singleton INSTANCE = new Singleton();
//to prevent creating another instance of Singleton
private Singleton(){}
public static Singleton getSingleton(){
return INSTANCE;
}
}
Si el constructor de una clase es privado, entonces no puede crear un objeto para la clase desde fuera de ella.
class Test{
int x, y;
private Test(){
.......
.......
}
}
No podemos crear un objeto para la clase anterior desde fuera de ella. Así que no puedes acceder a x, y desde fuera de la clase. Entonces, ¿cuál es el uso de esta clase?
Aquí está la respuesta: método de fábrica .
Agregue el siguiente método en la clase anterior
public static Test getObject(){
return new Test();
}
Así que ahora puedes crear un objeto para esta clase desde fuera de ella. De esa manera...
Test t = Test.getObject();
Por lo tanto, un método estático que devuelve el objeto de la clase mediante la ejecución de su constructor privado se llama método FACTORY
.
Todo se reduce a mantenimiento. La mejor manera de poner esto es cuando utiliza la new
palabra clave para crear un objeto, está acoplando el código que está escribiendo a una implementación.
El patrón de fábrica le permite separar cómo crea un objeto de lo que hace con el objeto. Cuando creas todos tus objetos usando constructores, esencialmente estás cableando el código que usa el objeto para esa implementación. El código que utiliza su objeto depende de ese objeto. Puede que esto no parezca un gran problema en la superficie, pero cuando el objeto cambia (piense en cambiar la firma del constructor o en la subclasificación del objeto), tiene que regresar y volver a cablear las cosas en todas partes.
Hoy en día, las fábricas han sido en gran parte excluidas a favor del uso de la inyección de dependencia porque requieren una gran cantidad de código de placa de caldera que resulta un poco difícil de mantener. La inyección de dependencia es básicamente equivalente a las fábricas, pero le permite especificar cómo se conectan sus objetos de forma declarativa (mediante configuración o anotaciones).
Un método de fábrica estático es bueno cuando quiere asegurarse de que solo una instancia va a devolver la clase concreta que se usará.
Por ejemplo, en una clase de conexión de base de datos, es posible que desee que solo una clase cree la conexión de base de datos, de modo que si decide cambiar de MySQL a Oracle, solo puede cambiar la lógica en una clase, y el resto de la aplicación Utiliza la nueva conexión.
Si desea implementar la agrupación de bases de datos, eso también se haría sin afectar al resto de la aplicación.
Protege el resto de la aplicación de los cambios que puede hacer en la fábrica, que es el propósito.
El motivo para que sea estático es si desea realizar un seguimiento de algunos recursos limitados (número de conexiones de socket o identificadores de archivos), entonces esta clase puede realizar un seguimiento de cuántos se han distribuido y devuelto, para que no agote la recurso limitado
Un método de fábrica, un método que abstrae la creación de instancias de un objeto. En general, las fábricas son útiles cuando sabe que necesita una nueva instancia de una clase que implementa alguna interfaz pero no conoce la clase implementadora.
Esto es útil cuando se trabaja con jerarquías de clases relacionadas, un buen ejemplo de esto sería un kit de herramientas GUI. Simplemente puede programar las llamadas a los constructores para implementaciones concretas de cada widget, pero si alguna vez desea intercambiar un conjunto de herramientas por otro, tendrá muchos lugares donde cambiar. Al utilizar una fábrica, reduce la cantidad de código que necesita cambiar.
Una de las ventajas de los métodos de fábrica estática con constructor privado (la creación de objetos debe haber sido restringida para clases externas para garantizar que las instancias no se creen externamente) es que puede crear clases controladas por instancias . Y las clases controladas por instancia garantizan que no existan dos instancias distintas ( a.equals (b) si y solo si se ejecuta a == b ) durante la ejecución de su programa, eso significa que puede verificar la igualdad de objetos con el operador == en lugar del método igual , de acuerdo con java eficaz.
La capacidad de los métodos de fábrica estática para devolver el mismo objeto a partir de invocaciones repetidas permite a las clases mantener un control estricto sobre las instancias existentes en cualquier momento. Las clases que hacen esto se dice que están controladas por instancia. Hay varias razones para escribir clases controladas por instancia. El control de instancia permite que una clase garantice que es un singleton (Elemento 3) o no institucionalizable (Artículo 4). Además, permite que una clase inmutable (Artículo 15) garantice que no existen dos instancias iguales: a.equals (b) si y solo si a == b. Si una clase hace esta garantía, sus clientes pueden usar el operador == en lugar del método igual (Objeto), lo que puede resultar en un mejor rendimiento. Los tipos de enumeración (artículo 30) proporcionan esta garantía.
De Effective Java, Joshua Bloch (Ítem 1, página 6)
Una de las ventajas que se deriva de Static Factory es que esa API puede devolver objetos sin hacer públicas sus clases. Esto condujo a una API muy compacta. En java, esto se logra mediante la clase Collections, que oculta alrededor de 32 clases, lo que la hace muy compacta.
Evitamos proporcionar acceso directo a las conexiones de base de datos porque requieren muchos recursos. Por lo tanto, utilizamos un método de fábrica estático getDbConnection
que crea una conexión si estamos por debajo del límite. De lo contrario, trata de proporcionar una conexión de "repuesto", fallando con una excepción si no hay ninguna.
public class DbConnection{
private static final int MAX_CONNS = 100;
private static int totalConnections = 0;
private static Set<DbConnection> availableConnections = new HashSet<DbConnection>();
private DbConnection(){
// ...
totalConnections++;
}
public static DbConnection getDbConnection(){
if(totalConnections < MAX_CONNS){
return new DbConnection();
}else if(availableConnections.size() > 0){
DbConnection dbc = availableConnections.iterator().next();
availableConnections.remove(dbc);
return dbc;
}else {
throw new NoDbConnections();
}
}
public static void returnDbConnection(DbConnection dbc){
availableConnections.add(dbc);
//...
}
}