@@ -121,29 +121,35 @@ sirva en cualquier aplicación:
121121 :language: java
122122 :class: toggle
123123 :caption: Clase Factory
124- :start-at: public class
124+ :start-at: public class Factory
125125
126126La principal diferencia (además de ser mucho más complicado que el anterior) es
127- que esta clase sí se instancia con el constructor ``Factory(String packageName,
128- Class<I> interfaceClass) `` para indicar en qué paquete se encuentran las clases
129- que implementan la interfaz y cuál es esta. En el ejemplo de nuestros
130- traductores:
127+ que esta clase sí se instancia con el constructor ``Factory(Class<I>, String) ``
128+ para indicar cuál es la interfaz implementada y en qué paquete se encuentran las
129+ clases que la implementan. En el ejemplo de nuestros traductores:
131130
132131.. code-block :: java
133132
134- Factory<Traductor > trFactory = new Factory<> (" edu.acceso.ejemplo.traductor" , Traductor . class);
133+ Factory<Traductor > factory = new Factory<> (Traductor . class, " edu.acceso.ejemplo.traductor" );
134+
135+ Ahora bien, si se coloca la interfaz en el mismo paquete que las clases, se
136+ puede omitir el segundo argumento:
137+
138+ .. code-block :: java
139+
140+ Factory<Traductor > factory = new Factory<> (Traductor . class);
135141
136142 La creación de este objeto *Factory * provoca que gracias a la reflexión se
137143analice el paquete y se localicen las clases que implementan la interfaz
138144(``Traductor `` en este caso). El objetivo es relacionar estas clases con su
139145nombre y, en su caso, con los nombres alternativos contenidos en el atributo
140- ``aliases ``. Por ejemplo:
146+ ``alias ``. Por ejemplo:
141147
142148.. code-block :: java
143149
144150 public class TYaml implements Traductor {
145151 // También podría ser String si sólo hay una alternativa
146- private static final String[] = {" yml" , " yaml" };
152+ private static final String [] alias = {" yml" , " yaml" };
147153
148154 // Implementación de la traducción para YAML...
149155 }
@@ -157,11 +163,34 @@ traducción, nos bastaría con hacer:
157163
158164 String formato = " yml" ; // Por ejemplo.
159165
160- Factory<Traductor > trFactory = new Factory<> (" edu.acceso.ejemplo.traductor" , Traductor . class);
161- Traductor traductor = trFactory. getObject(formato);
166+ // Suponemos que Traductor y TYaml están en el mismo paquete.
167+ Factory<Traductor > factory = new Factory<> (Traductor . class);
168+ Class<? extends Traductor > traductorClass = factory. get(formato);
169+
170+ Y ya tendríamos disponible la clase que implementa |YAML | para instanciarla
171+ cuando nos sea necesario. También existe la posibilidad de pedir directamente la
172+ instancia:
173+
174+ .. code-block :: java
175+
176+ Traductor traductor = factory. getInstance(formato);
177+
178+ .. caution :: Este método sólo funcionará si el constructor de las clases no
179+ tiene argumentos y, además, la construcción no tiene dependencias cruzadas
180+ en el programa. Por ejemplo, si utilizamos :ref: `una clase para gestionar la
181+ configuración de usuario <cliargs>` es probable que echemos mano de esta
182+ clase ``Factory ``. Si el constructor del traductor hace
183+ uso a su vez de la configuración entonces tendremos una dependencia circular:
184+ para construir el objeto de configuración necesitamos un objeto traductor,
185+ pero para construir un objeto traductor necesitamos la configuración.
186+
187+ Por lo general es más seguro obtener la clase del traductor e instanciar
188+ nosotros luego. Justamente en el caso anterior, podríamos obtener la clase
189+ del traductor para definir el atributo del objeto ``Config `` y en el *getter *
190+ de ese atributo, hacer la instanciación.
162191
163- La clase tiene, además, dos métodos adicionales que sirven básicamente para
164- brindar información:
192+ La clase tiene, además, otros dos métodos adicionales que sirven básicamente
193+ para brindar información:
165194
166195``getClasses() ``
167196 que devuelve un mapa en que las claves son las cadenas y los valores las
@@ -171,15 +200,4 @@ brindar información:
171200 que devuelve un mapa en que cada clave es una clase y los valores un array
172201 con todos los nombres con los que está relacionada.
173202
174- .. warning :: El ćodigo tiene una limitación: el constructor de las clases no
175- puede tener argumentos. En caso de que debiera tenerlos, no obstante, es
176- fácil soslayar la limitación: bastaría con incluir en la interfaz un método
177- inicializador. Por ejemplo:
178-
179- .. code-block :: java
180-
181- public interface Foobar {
182-
183- public void initialize ( /* Los argumentos que sea */ );
184- // Resto de métodos que definen la interfaz.
185- }
203+ .. |YAML | replace :: :abbr: `YAML ( YAML Ain't Markup Language ) `
0 commit comments