Está en la página 1de 7

Franco Guidi Polanco 1

Abstract Factory (Fbrica abstracta -GoF)

Descripcin

Presenta una interfaz para la creacin de familias de productos, de forma tal que el
cliente que las utiliza no requiera conocer las clases concretas que la componen. Esto
fuerza al cliente a crear solamente productos relacionados entre si, a la vez que lo
habilita para la utilizacin de distintas familias de productos.

Ejemplo

Un negocio de venta de equipos musicales efecta demostraciones del uso de sus


distintos productos. Los productos se agrupan en familias segn la tecnologa en la
que se basan, como por ejemplo la familia de equipos que utilizan compact disc (CD),
o la familia de equipos basados en cinta magntica. Independientemente del caso, se
supondr que cada familia est compuesta por un medio en que se registra la msica,
un dispositivo que realiza el registro en el respectivo medio, y otro que la reproduce
(ver Fig x.1).

Grabador CD Reproductor

Grabador Cinta magntica Reproductor

Fig. x.1

Si estos productos ofrecieran a sus usuarios la misma interfaz, un cliente podra reali-
zar el mismo proceso de prueba de productos en cualquiera de las familias. Por ejem-
plo, podra registrar una cancin utilizando el dispositivo de grabacin, para luego es-
cucharlo en el dispositivo de reproduccin. Slo deberamos asegurarnos que los pro-
ductos sean compatibles entre si, esto es, que todos ellos pertenezcan a una misma
familia.

El problema consiste en la definicin de un mecanismo que permita al cliente crear y


utilizar familias completas de productos, sin tener conocimiento de cules son los inte-
grantes concretos de la familia.

Descripcin de la solucin ofrecida por el patrn de diseo

La definicin de interfaces constituye el mecanismo mediante el cual es posible ocultar


la implementacin de una clase en aquellas porciones de cdigo en que son utilizadas.
En consecuencia, la definicin de interfaces comunes para aquellos productos anlo-
gos pertenecientes a diferentes familias, permitir a un mismo cliente realizar opera-
ciones similares sobre artefactos de tecnologas distintas. El problema surge cuando el
cliente debe manejar familias cuyos productos no deben entremezclarse. Por ejemplo,
Franco Guidi Polanco 2

si se pretende utilizar un grabador de CD el cliente debe instanciarlo junto con un CD y


un reproductor de CD, no con una cinta magntica o un reproductor de DVD. La sola
definicin de interfaces para los productos no garantiza que el cliente se limite a crear
slo productos de una misma familia.

El patrn de diseo Abstract Factory resuelve este problema por medio de la encapsu-
lacin de reglas de instanciacin. sta permite ocultar en una clase fbrica el proce-
so de instanciacin de un conjunto de productos. Por su parte, la encapsulacin de los
productos tras interfaces comunes permitir al cliente utilizar productos anlogos per-
tenecientes a familias diferentes.

Los nefitos en el campo de los patrones de diseo suelen cuestionarse la diferencia


entre este patrn y el Factory Method, puesto que ambos presentan una estructura
similar, al encapsular en una clase el proceso de instanciacin de un objeto. La dife-
rencia radica en que, mientras el Factory Method tiene por objetivo diferir hacia una
determinada clase (o subclase) el tipo de producto a instanciar, el patrn Abstract Fac-
tory persigue garantizar la creacin de un conjunto de productos relacionados.

La implementacin de este patrn requiere definicin de una interfaz adicional a la de


los productos: la interfaz que implementarn las fbricas encargadas de generarlos, y
que permitir al cliente interactuar con ellas. Esta interfaz proveer los mtodos cuyo
contrato consistir en retornar instancias de cada tipo de producto dentro de una fami-
lia. En el caso del ejemplo, la interfaz de las fbricas permitir al cliente solicitar la ge-
neracin de instancias de grabador, de medios de registro y de reproductores. De esta
forma, el cliente no deber invocar en caso alguno el constructor de los productos,
quedando absolutamente desligado de la implementacin particular de estos ltimos.

Estructura del patrn de diseo

<<stereotipe>>
Client

<<stereotipe>> <<stereotipe>>
AbstractFactory AbstractProduct
{abstract} {abstract}

+createProduct() : AbstractProduct {abstract}

<<stereotipe>>
<<stereotipe>> <<instantiates>> ConcreteProduct
ConcreteFactory produces

#ConcreteProduct()
+createProduct() : AbstractProduct

Fig. x.2
Franco Guidi Polanco 3

Aplicacin de patrn de diseo

Esquema

<<Interface>>
DevicesFactory
Client
+ createPlayer() : Player
+ createRecorder() : Recorder
+ createMedia() : Media

<<Interface>>
Media

CD Devices Tape Devices


Fact ory Factory

Tape CD

+ saveOnTape(String sound) + writeOnDisk(String sound)


+ readTape() : String + readDisk() : String

<<Interface>>
Recorder

+ accept(Media)
+ record()

Tape Recorder CD Recorder

<<Interface>>
Player

+ ac cept(Media)
+ play()

Tape Player CD Player

Fig. x.3

Participantes
AbstractFactory (Fbrica Abstracta): interfaz DevicesFactory.
- Declara una interfaz para las operaciones que crean y restituyen productos.
- En la declaracin de cada mtodo, los productos restituidos son del tipo
AbstractProduct.
ConcreteFactory (Fbrica concreta): classes TapeDevicesFactory y
CDDevicesFactory.
- Cada una de estas clases Implementa la interfaz de la AbstractFactory (De-
vicesFactory), especificando las operaciones que crean y retornan ob-
jetos correspondientes a productos especficos (ConcreteProduct).
AbstractProduct: interfaces Media, Recorder y Player.
- Declaran las operaciones que caracterizan a los distintos tipos genricos de
productos.
ConcreteProduct: clases Tape, TapeRecorder, TapePlayer, CD, CDRecorder y
CDPlayer.
- Definen los productos creados por cada ConcreteFactory.
Franco Guidi Polanco 4

Client: clase Client.


- Utiliza la interfaz de la AbstractFactory (DevicesFactory) para acceder a los
mtodos de la ConcreteFactory correspondiente a una familia de productos.
- Utiliza los productos a travs de su interfaz AbstractProduct.

Descripcin del cdigo

En primer lugar, se definen las interfaces de las clases que debern implementar los
productos anlogos pertenecientes a las distintas familias. En el caso de este ejemplo,
Media es la interfaz que implementan los soportes de grabacin. Particularmente esta
interfaz no especifica mtodos, slo acta como una interfaz para marcar su rol. Por
su parte, las interfaces Player y Recorder definen las interfaces de reproductores y
grabadores, especificando los distintos mtodos con los cuales el cliente interactuar
con ellas.
public interface Media { }

public interface Player {


public void accept( Media med );
public void play( );
}

public interface Recorder {


public void accept( Media med );
public void record( String sound );
}

Los productos de las distintas familias implementan las interfaces definidas anterior-
mente. En el caso de la familia de productos basada en el casete, los productos son
Tape, TapeRecorder y TapePlayer:

public class Tape implements Media {

private String tape= "";

public void saveOnTape( String sound ) {


tape = sound;
}

public String readTape( ) {


return tape;
}

public class TapeRecorder implements Recorder {

Tape tapeInside;

public void accept( Media med ) {


tapeInside = (Tape) med;
}

public void record( String sound ) {


if( tapeInside == null )
System.out.println( "Error: Insert a tape." );
else
tapeInside.saveOnTape( sound );
}

}
Franco Guidi Polanco 5

public class TapePlayer implements Player {

Tape tapeInside;

public void accept( Media med ) {


tapeInside = (Tape) med;
}

public void play( ) {


if( tapeInside == null )
System.out.println( "Error: Insert a tape." );
else
System.out.println( tapeInside.readTape() );
}

Por su parte, los productos pertenecientes a la familia del CD son:


public class CD implements Media{

private String track = "";

public void writeOnDisk( String sound ) {


track = sound;
}

public String readDisk( ) {


return track;
}

public class CDRecorder implements Recorder {

CD cDInside;

public void accept( Media med ) {


cDInside = (CD) med;
}

public void record( String sound ) {


if( cDInside == null )
System.out.println( "Error: No CD." );
else
cDInside.writeOnDisk( sound );
}

public class CDPlayer implements Player {

CD cDInside;

public void accept( Media med ) {


cDInside = (CD) med;
}

public void play( ) {


if( cDInside == null )
System.out.println( "Error: No CD." );
else
System.out.println( cDInside.readDisk() );
}

La interfaz DevicesFactory declara los mtodos que utilizar el cliente para interac-
tuar con las fabricas de productos. Ntese que cada mtodo tiene la funcin de crear
un tipo de producto especfico:
public interface DevicesFactory {
Franco Guidi Polanco 6

public Player createPlayer();


public Recorder createRecorder();
public Media createMedia();

Las clases TapeDevicesFactory y CDDevicesFactory corresponden a las fbri-


cas de productos de las diferentes familias. Estas clases corresponden a las Concrete-
Factory para la creacin de productos correspondientes a las familias basadas en case-
te en CD, respectivamente.
public class TapeDevicesFactory implements DevicesFactory {

public Player createPlayer() {


return new TapePlayer();
}

public Recorder createRecorder() {


return new TapeRecorder();
}

public Media createMedia() {


return new Tape();
}

public class CDDevicesFactory implements DevicesFactory {

public Player createPlayer() {


return new CDPlayer();
}
public Recorder createRecorder() {
return new CDRecorder();
}
public Media createMedia() {
return new CD();
}

La clase Client es la que finalmente solicita la instanciacin de los productos, y los


utiliza. El Client accede tanto a la fbrica de productos, como a los productos mis-
mos a travs de sus interfaces comunes. Esto permite al Client utilizar tanto los pro-
ductos basados en casete, como aquellos basados en CD (como tambin, cualquier
otra familia que adhiera a las interfaces ya declaradas). El Client de este ejemplo
implementa el mtodo selectTechnology recibe una instancia de fbrica, la cual es
utilizada en el interior del mtodo test para crear los productos y utilizarlos. Se debe
notar que la clase Client crea y utiliza los productos sin tener conocimiento acerca
de qu tipo especfico de producto est usando.
class Client {

DevicesFactory technology;

public void selectTechnology( DevicesFactory df ) {


technology = df;
}

public void test(String song) {

Media media = technology.createMedia();


Recorder recorder = technology.createRecorder();
Player player = technology.createPlayer();
recorder.accept( media );
System.out.println( "Recording the song : " + song );
recorder.record( song );
System.out.println( "Listening the record:" );
Franco Guidi Polanco 7

player.accept( media );
player.play();
}

Finalmente se presenta la aplicacin que crea una instancia de Client, y le asigna


las distintas fbricas de productos para su utilizacin.

public class AbstractFactoryExample {

public static void main ( String[] arg ) {

Client client = new Client();

System.out.println( **Testing tape devices );


client.selectTechnology( new TapeDevicesFactory() );
client.test( "I wanna hold your hand..." );

System.out.println( **Testing CD devices );


client.selectTechnology( new CDDevicesFactory() );
client.test( "Fly me to the moon..." );

Observaciones respecto del ejemplo

En este ejemplo se ha querido destacar la necesidad de que el cliente deba crear slo
productos de una misma familia. En particular se debe notar que los mtodos que
ofrece la clase CD y la clase Tape, y que son utilizados por los respectivos grabadores
y reproductores, son distintos. Este hecho, resulta irrelevante al momento de crear los
productos, pues la consistencia de la creacin de objetos es garantizada por la clase
fbrica.

Ejecucin del ejemplo


C:\Patterns\Creational\Abstract Factory\>java AbstractFactoryExample

**Testing tape devices


Recording the song : I wanna hold your hand...
Listening the record:
I wanna hold your hand...

**Testing CD devices
Recording the song : Fly me to the moon...
Listening the record:
Fly me to the moon...

Observaciones sobre el patrn

Debido a que, tanto la AbstractFactory, como los AbstractProduct de este ejemplo no im-
plementan operaciones, en Java resulta ms adecuado codificarlos como interfaces,
en vez de clases abstractas, como se sugiere en [Gamma].

Otros ejemplos

Una compaa que produce videojuegos est interesada en crear un juego en el cual
el usuario debe escoger un personaje que lo representar a lo largo de una aventura,
junto con ciertas herramientas que ste puede utilizar. Las herramientas dependen del
personaje elegido, sin embargo, el cdigo que regula la operacin es idntico para
cualquier personaje.

También podría gustarte