factory method

51
Factory Method (patrón de diseño) En diseño de software , el patrón de diseño Factory Method consiste en utilizar una clase constructora (al estilo del Abstract Factory) abstracta con unos cuantos métodos definidos y otro(s) abstracto(s): el dedicado a la construcción de objetos de un subtipo de un tipo determinado. Es una simplificación del Abstract Factory , en la que la clase abstracta tiene métodos concretos que usan algunos de los abstractos; según usemos una u otra hija de esta clase abstracta, tendremos uno u otro comportamiento. Estructura[editar · editar código ] Las clases principales en este patrón son el creador y el producto. El creador necesita crear instancias de productos, pero el tipo concreto de producto no debe ser forzado en las subclases del creador, porque las posibles subclases del creador deben poder especificar subclases del producto para utilizar. La solución para esto es hacer un método abstracto (el método de la fábrica) que se define en el creador. Este método abstracto se define para que devuelva un producto. Las subclases del creador pueden sobrescribir este método para devolver subclases apropiadas del producto... Ejemplo de código (en Java)[editar · editar código ] abstract class Creator{ // Definimos método abstracto public abstract Product factoryMethod(); } Ahora definimos el creador concreto.

Upload: jorge-gonzales-castillo

Post on 29-Nov-2015

280 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Factory Method

Factory Method (patrón de diseño)En diseño de software, el patrón de diseño Factory Method consiste en utilizar una clase

constructora (al estilo del Abstract Factory) abstracta con unos cuantos métodos definidos y otro(s)

abstracto(s): el dedicado a la construcción de objetos de un subtipo de un tipo determinado. Es una

simplificación del Abstract Factory, en la que la clase abstracta tiene métodos concretos que usan

algunos de los abstractos; según usemos una u otra hija de esta clase abstracta, tendremos uno u

otro comportamiento.

Estructura[editar · editar código]

Las clases principales en este patrón son el creador y el producto. El creador necesita crear

instancias de productos, pero el tipo concreto de producto no debe ser forzado en las subclases del

creador, porque las posibles subclases del creador deben poder especificar subclases del producto

para utilizar.

La solución para esto es hacer un método abstracto (el método de la fábrica) que se define en el

creador. Este método abstracto se define para que devuelva un producto. Las subclases del creador

pueden sobrescribir este método para devolver subclases apropiadas del producto...

Ejemplo de código (en Java)[editar · editar código]

abstract class Creator{

// Definimos método abstracto

public abstract Product factoryMethod();

}

Ahora definimos el creador concreto.

public class ConcreteCreator extends Creator{

public Product factoryMethod() {

return new ConcreteProduct();

}

}

Page 2: Factory Method

Y definimos el producto y su implementación concreta.

public interface Product{

public void operacion();

}

public class ConcreteProduct implements Product{

public void operacion(){

System.out.println("Una operación de este producto");

}

}

Y un ejemplo de uso :

public static void main(String args[]){

Creator aCreator;

aCreator = new ConcreteCreator();

Product producto = aCreator.factoryMethod();

producto.operacion();

}

Abstract FactoryAbstract Factory (Fábrica Abstracta) es un patrón de diseño para el desarrollo de software.

Índice

  [ocultar] 

1   Contexto y problema

2   Aspecto estático

3   Un ejemplo

4   Véase también

5   Enlaces externos

Contexto y problema[editar · editar código]

Contexto: Debemos crear diferentes objetos, todos pertenecientes a la misma familia. Por ejemplo:

las bibliotecas para crear interfaces gráficas suelen utilizar este patrón y cada familia sería un

sistema operativo distinto. Así pues, el usuario declara un Botón, pero de forma más interna lo que

está creando es un BotónWindows o un BotónLinux, por ejemplo.

El problema que intenta solucionar este patrón es el de crear diferentes familias de objetos.

Page 3: Factory Method

El patrón Abstract Factory está aconsejado cuando se prevé la inclusión de nuevas familias de

productos, pero puede resultar contraproducente cuando se añaden nuevos productos o cambian

los existentes, puesto que afectaría a todas las familias creadas.

Aspecto estático[editar · editar código]

La estructura típica del patrón Abstract Factory es la siguiente:

Cliente: La clase que llamará a la factoría adecuada ya que necesita crear uno de los objetos

que provee la factoría, es decir, Cliente lo que quiere es obtener una instancia de alguno de los

productos (ProductoA, ProductoB).

Page 4: Factory Method

AbstractFactory: Es la definición de la interfaces de las factorías. Debe de proveer un método

para la obtención de cada objeto que pueda crear. ("crearProductoA()" y "crearProductoB()")

Factorías Concretas: Estas son las diferentes familias de productos. Provee de la instancia

concreta de la que se encarga de crear. De esta forma podemos tener una factoría que cree los

elementos gráficos para Windows y otra que los cree para Linux, pudiendo poner fácilmente

(creando una nueva) otra que los cree para MacOS, por ejemplo.

Producto abstracto: Definición de las interfaces para la familia de productos genéricos. En el

diagrama son "ProductoA" y "ProductoB". En un ejemplo de interfaces gráficas podrían ser

todos los elementos: Botón, Ventana, Cuadro de Texto, Combo... El cliente trabajará

directamente sobre esta interfaz, que será implementada por los diferentes productos

concretos.

Producto concreto: Implementación de los diferentes productos. Podría ser por ejemplo

"BotónWindows" y "BotónLinux". Como ambos implementan "Botón" el cliente no sabrá si está

en Windows o Linux, puesto que trabajará directamente sobre la superclase o interfaz.

Un ejemplo[editar · editar código]

Veremos un ejemplo didáctico y basado en el libro Head First Design Patterns, de O'Reilly.

Supongamos que disponemos de una cadena de pizzerías. Para crear pizzas disponemos de un

método abstracto en la clase Pizzería que será implementada por cada subclase de Pizzería.

abstract Pizza crearPizza()

Concretamente se creará una clase PizzeríaZona por cada zona, por ejemplo la Pizzería de New

York sería PizzeriaNewYork y la de Californía PizzeríaCalifornia que implementarán el método con

los ingredientes de sus zonas.

Las pizzas son diferentes según las zonas. No es igual la pizza de New York que la pizza de

California. Igualmente, aunque usarán los mismos ingredientes (tomate, mozzarella...) no los

obtendrán del mismo lugar, cada zona los comprará donde lo tenga más cerca. Así pues podemos

crear un método creador de Pizza que sea

Pizza(FactoriaIngredientes fi);

Como vemos utilizamos la factoría abstracta (no las concretas de cada zona, como podría ser

IngredientesNewYork o IngredientesCalifornia). Pizza podrá obtener los ingredientes de la factoría

independientemente de donde sea. Sería fácil crear nuevas factorías y añadirlas al sistema para

crear pizzas con estos nuevos ingredientes. Efectivamente, en este ejemplo cliente es Pizza y es

independiente de la Factoría usada.

Page 5: Factory Method

El creador de la Pizza será el encargado de instanciar la factoría concreta, así pues los encargados

de instanciar las factorías concretas serán las pizzerías locales. En PizzeríaNewYork podemos tener

el método crearPizza() que realice el siguiente trabajo:

Pizza crearPizza() {

FactoríaIngredientes fi = new IngredientesNewYork();

Pizza pizza = new Pizza(fi); // Uso de la factoría

pizza.cortar();

pizza.empaquetar();

return pizza;

}

Como conclusión podemos observar que gracias a la factoría de ingredientes crear una nueva zona,

por ejemplo una pizzería en Barcelona, no nos implicaría estar modificando el código existente, solo

deberemos extenderlo (uno de los pilares de la Ingeniería del software) ya crearíamos la subclase

de Pizzería: PizzeríaBarcelona que al instanciar la factoría solo debería escoger la factoría de

Barcelona. Obviamente se debería crear la factoría de Barcelona que se encargaría de crear los

productos obtenidos de Barcelona. Así que en ningún momento modificamos las pizzerías

existentes, la superclase pizzería o las otras factorías o productos, solo creamos nuevas clases.

Abstract Factory

El patrón Abstract Factory nos permite crear, mediante una interfaz, conjuntos o familias

de objetos (denominados productos) que dependen mutuamuente y todo esto sin

especificar cual es el objeto concreto.

¿Que usos tiene el patrón Abstract Factory?

Este patrón se puede aplicar cuando:

o Un sistema debe ser independiente de como sus objetos son creados.

o Un sistema debe ser 'configurado' con una cierta familia de productos.

o Se necesita reforzar la noción de dependencia mutua entre ciertos objetos.

Page 6: Factory Method

Estructura del Patrón Abstract Factory

El asterisco (*) representa que la clase/operación es abstracta.

Elementos del Patrón Abstract Factory

FabricaAbstracta*: Define un conjunto de métodos (interfaz) para la creación de

productos abstractos.

o FabricaConcreta1/2: Implementa la interfaz de la FabricaAbstracta para la creación

de los distintos productos concretos.

o ProductoAbstractoA*/B*: Define la interfaz de los objetos de tipo ProductoA/B.

o ProductoConcretoA1/A2/B1/B2: Implementan su respectiva interfaz representando

un producto concreto.

Page 7: Factory Method

Pros/Contras del Patrón Abstract Factory

o + Brinda flexibilidad al aislar a las clases concretas.

o + Facilita cambiar las familias de productos.

o - Para agregar nuevos productos se deben modificar tanto las fabricas abstractas

como las concretas.

Ejemplo del Patrón Abstract Factory

Teniendo en cuenta la siguiente jerarquía de clases, la cual trata de representar muy por

arriba dos familias de productos (DVD y BluRay) cada uno con un par de variantes (simple

y doble capa) para que permiten mostrar diferentes aspectos a tener en cuenta a la hora

de usar este patrón.

Vemos como sería el producto abstracto:

1. public abstract class Disco implements Prototipo {

2. @Override

3. public abstract Prototipo clone();

4.  

5. public abstract String getCapacidad();

6.  

7. public abstract String getNombre();

8.  

9. public abstract String getPrecio();

10.  

11. @Override

Page 8: Factory Method

12. public String toString() {

13. return getNombre() + " (" + getCapacidad() + ")";

14. }

15. }

El producto DVD extendemos del Disco

1. public abstract class DVD extends Disco {

2. ...

3. }

Y el producto concreto del DVD extenderá de la anterior clase:

1. public class DVD_CapaSimple extends DVD {

2.  

3. @Override

4. public Prototipo clone() {

5. return new DVD_CapaSimple();

6. }

7.  

8. @Override

9. public String getCapacidad() {

10. return "4.7GB";

11. }

12.  

13. @Override

14. public String getNombre() {

15. return "DVD Capa Simple";

16. }

17.  

18. @Override

19. public String getPrecio() {

20. return "5.00$";

21. }

22.  

23. }

Vamos a construir un AbstractFactory que nos permita crear discos de DVD o BluRay de

simple y doble capa usando el siguiente diseño:

Page 9: Factory Method

La factoría abstracta la definiríamos mediante un interface:

1. public interface FabricaDiscos {

2.  

3. public BluRay crearBluRay();

4. public DVD crearDVD();

5. }

Y sobre ese interface implementamos una de las fábricas concretas, en este caso la de

FabricaDiscos_CapaSimple:

1. public class FabricaDiscos_CapaSimple implements FabricaDiscos {

2.  

3. @Override

4. public BluRay crearBluRay() {

5. return new BluRay_CapaSimple();

6. }

7.  

8. @Override

9. public DVD crearDVD() {

10. return new DVD_CapaSimple();

11. }

12.  

13. }

Veamos como quedaría el código fuente en Java para utilizar el patrón Abstract Factory:

1. FabricaDiscos fabrica;

2. DVD dvd;

Page 10: Factory Method

3. BluRay bluray;

4.  

5. fabrica = new FabricaDiscos_CapaSimple();

6. dvd = fabrica.crearDVD();

7. bluray = fabrica.crearBluRay();

8.  

9. System.out.println(dvd);

10. System.out.println(bluray);

11.  

12. fabrica = new FabricaDiscos_CapaDoble();

13. dvd = fabrica.crearDVD();

14. bluray = fabrica.crearBluRay();

15.  

16. System.out.println(dvd);

17. System.out.println(bluray);

En el código vemos que sobre la fábrica podemos crear objetos de diferentes tipos y que

podríamos ir creciendo en productos atendiendo a nuestras necesidades.

1. fabrica = new FabricaDiscos_CapaSimple();

2. dvd = fabrica.crearDVD();

3. bluray = fabrica.crearBluRay();

Espero que hayáis podido apreciar la flexibilidad que nos brinda el patrón Abstract Factory.

Los patrones de diseño son soluciones que se puede aplicar a problemas

recurrentes en el diseño de software, los mismos cubren aspectos como la creación

e interacción de objetos así como la comunicación entre ellos, ademas estos nos

hacen mas fácil el reutilizar componentes de software basándose en técnicas ya

probadas una y otra vez en distintas aplicaciones pudiendo realizar diseños de una

manera mas rápida y simplificada.

Los patrones de diseño se dividen en tres grupos: creacionales, estructurales, y de

comportamiento, en este primer post empezare hablando del patrón creacional

Abstract Factory.

Definicion de Abstract Factory: este patrón nos provee una interfaz  para crear

familias de objetos relacionados o dependientes entre ellos sin especificar una clase

en concreto.

Page 11: Factory Method

Diagrama UML

Participantes:

AbstractFactory: declara una interfaz para operaciones que crean un producto

abstracto

ConcreteFactory : implementa la operación para crear un producto en concreto

AbstractProduct  : declara una interfaz para un tipo de producot en concreto

Product: define un producto que será creado por su ConcreteFactory

correspondiente e implementa la interfaz AbstractProduct

Client:  usa la interfaz declarada por el AbstractFactory   y AbstractProduct

Entre los problemas mas comunes resueltos por el patrón Abstract Factory se

encuentra:

- La creación de un objeto creando su tipo de manera dinámica de forma que no nos

veamos atados a una implementación sino a una interfaz haciendo mas fácil los

cambios futuros.

-  Nos permite jugar con la manera de satisfacer las peticiones hacia

una operación determinada, de esta manera es mas sencillo cambiar la forma en

que se atienden las peticiones desde una operación en concreto.

Page 12: Factory Method

- Nos permite poder manejarnos entre distintas plataformas de hardware  y

software al poder ser capaces de realizar diferentes manejos de

las peticiones basándonos en las plataformas.

También es muy usado en casos donde se requiere crear una librería de clases  de

productos ya que solo revelamos sus interfaces mas no su implementación .

Creando objetos con el diseño Abstract Factory.        Factory, es un patrón de diseño. En distintas paginas de la web los patrones de diseño son definidos como:    “soluciones simples y elegantes a problemas específicos y comunes del diseño orientado a objetos. Son soluciones basadas en la experiencia y que se ha demostrado que funcionan”. Existen distintos patrones, como el command, singleton, etc, pero en este post solo hablaremos de Factory o Fábrica, especificamente con Abstract Factory o Fábrica Abstracta.

       Entonces, ¿Qué hace factory?, "este patrón delega en una clase la responsabilidad de creación de objetos de otras clases. Puede evolucionar a un Factory Method o a un Abstract Factory".

Factory Method: "define una interfaz para crear objetos, pero deja que sean las subclases quienes decidan qué clases instanciar; permite que una clase delegue en sus subclases la creación de objetos." Abstract Factory: " El patrón Abstract Factory proporciona una interfaz para crear familias de objetos relacionados o que dependen entre sí, sin especificar sus clases concretas". "Normalmente se implementa usando Factory Method".

            Para entender un poco mejor el diseño Abstract Factory, he creado un pequeño ejemplo en java, para este, se me ocurrió plantear lo siguiente: una empresa de Servicios de comunicación cualquiera, puede tener varios productos que ofrecer para permitir que sus usuarios se comuniquen. Se pueden encontrar teléfonos móviles, teléfonos fijos, internet y  tal vez otros mas. En el caso de los teléfonos para poder establecer una comunicación se necesitan los códigos de área para el caso de los fijos (más el número telefónico), y los de la compañía para el caso de los móviles, sin embargo para el internet no necesito este tipo de códigos, puesto que en un principio (y para este ejemplo) no realiza llamadas.

Page 13: Factory Method

       Comencé creando una interfaz llamada Servicio, donde únicamente declaro un método, que para este ejemplo es llamado codigoDeServicio, pues de cada servicio ofrecido por la compañía voy a querer saber el distinto tipo de código usado, para llamar.

       Cree también otra interfaz de tipo Servicio llamada ServicioDeComunicacion, y declaro en ella un método, para la creación, que se encargaran de implementar cada fabrica.

       

       La idea siguiente sería, crear tres clases: TelefonoMovil, TelefonoFijo e Iternet, que implementaran la interfaz Servicio, como cada clase lo requiera. Para este ejemplo, estas clases solo imprimirán el código que se necesite para realizar una llamada.

Page 15: Factory Method

       Como después voy a querer manejar varios de estos objetos, creo las clases fábricas, que implementaran la interfaz ServicioDeComunicacion:

Page 16: Factory Method

       Termino encapsulando (por decirlo de alguna manera) las tres fábricas anterios, creando una clase FabricaPrincipal que posea un metodo para crear cualquier tipo de fábrica que se pase por parametro, aseguro esto porque el tipo de dato de lo que recibe el metodo, es ServicioDeComunicacion (interfaz que implementa cada una de las fábricas)

Page 17: Factory Method

       Finalmente hago un main, para mandar a crear un objeto, para este ejemplo hice un pequeño switch, e inicialice una variable en 1, para crear un objeto TelefonoMovil, desde su fabrica.

Patrones de Diseño Software de Creación

Introducción

Los patrones de diseño software de creación proporcionan ayuda a la hora de crear objetos

desde el punto de vista de proporcionar un apopyo en la toma de decisiones, incluso cuando

esta toma de decisiones sea de forma dinámica.

Gracias a ello, ayudan a estructurar y encapsular estas decisiones. Hay ocasiones en la que

nos encontraremos con que sólo existe un patrón adecuado; otras en las que varios podrán

ayudarnos; y otras en que se pueden combinar múltiples patrones convenientemente.

Un patrón de creación asociado a clases usa la herencia para variar la clase que se instancia,

mientras que un patrón de diseño software de creación asociado a objetos delegará la

instanciación a otro objeto.

Hay dos formas de clasificar los patrones de diseño software de creación basándose en las

clases de objetos que se crean. Una es clasificar las clases que crean los objetos (Factory

Method), y la otra forma está relacionada con la composición de objetos (definir un objeto

que es responsable de conocer las clases de los objetos producto). En esta característica se

apoyan los patrones Abstract Factory, Builder o Prototype.

En muchas ocasiones los patrones de creación compiten en su función. Por ejemplo, hay

casos donde los patrones de creación Protoype y Abstract Factory puede utilizarse

indistintamente. En otras ocasiones Builder puede usar a los otros patrones para implementar

los componentes que construye.

A continuación, definiremos algunos de los patrones de diseño software de creación más

habituales.

Page 18: Factory Method

Abstract Factory

Nos encontramos frente a un problema en el que debemos crear diferentes objetos, todos

pertenecientes a la misma familia, como puede ser el sistema de librerías necesarias para

crear interfaces gráficas. Visto esto podríamos decir que lo que intenta solucionar el patrón

de diseño software de creación Abstract Factory es crear diferentes familias de objetos. El

patrón Abstract Factory, por tanto, se recomienda cuando se atisba la inclusión de nuevas

familias de productos en un futuro, pero resultaría contraproducente si que necesita añadir

nuevos productos o modificar los existentes, ya que tendría repercusión en todas las familias

creadas.

Según esto, podemos decir que los componentes típicos del patrón Abstract Factory es la

siguiente:

Cliente:  Entidad que llamará a la fábrica adecuada que necesite para crear uno de los objetos que provee dicha factoría, es decir, intentará obtener una instancia de alguno de los productos que entren en juego (ProductoA, ProductoB).

AbstractFactory:  Definición de la interfaz que usarán las diferentes factorías. Como mínimo, debe ofrecer un método para la obtención de cada objeto que se pueda crear. ("crearProductoA()" y "crearProductoB()")

Concrete Factories:  Aquí se representarán las diferentes familias de productos. Provee la instancia concreta del objeto que se encarga de crear.

Abstract Product:  Definirá las interfaces para la familia de productos genéricos. En el diagrama son "ProductoA" y "ProductoB". El cliente trabajará directamente sobre esta interfaz, que será implementada por los diferentes productos concretos.

Concrete Product:  Se encargará de la implementación específica de los diferentes productos.

Este sería el diagrama de clases general del patrón de creación Abstract Factory:

Esquema del patrón Abstract Factory

Page 19: Factory Method

En este enlace podrá consultar un código de ejemplo en Java del patrón de creación

Abstract Factory.

Factory Method

Este patrón de diseño software de creación consiste en utilizar una clase constructora

abstracta (similar al concepto del patrón Abstract Factory) con unos métodos definidos y

otro(s) abstracto(s): el(los) dedicado(s) a la construcción de objetos de un subtipo

determinado.

Como vemos, es una simplificación del Abstract Factory, en la que la clase abstracta tiene

métodos concretos que se relacionan con los abstractos, de modo que según usemos una u

otra "hija" de esta clase abstracta, tendremos uno u otro comportamiento.

El patrón de diseño software de creación Factory Method puede ser usado cuando:

La creación de un objeto impide su reutilización sin una importante duplicación de código.

La creación de un objeto requiere acceso a la información o recursos que no deberían estar contenidos en la clase de composición.

La administración de la duración de los objetos generados debe ser centralizada para garantizar un comportamiento coherente en la aplicación.

Por tanto, los componentes del patrón de creación Factory Method sería:

Product:  define una interfaz de un objeto que metodo Factory creara. ConcreteProduct:  implementa la interfaz Product para crear un producto en concreto. Creator:  declara el metodo factory que devolvera un objeto del tipo product. ConcreteCreator:  sobre escribe e metodo factory del creator devoler una intancia de

un producto en concreto (ConcreteProduct).

Este sería el diagrama de clases general de este patrón de creación:

Page 20: Factory Method

Esquema del patrón Factory Method

En este enlace podrá consultar un código de ejemplo en Java del patrón de creación

Factory Method.

Prototype

El patrón de diseño de software de creación Prototype, sirve para crear un duplicado de un

objeto, clonando, para ello, una instancia de ese objeto que ya haya sido creada. Para ello, el

patrón tiene que especificar el tipo de objeto que quiere clonar, creando así un 'prototipo' de

esa instancia. Este tipo o clase de objetos deberá contener en su interfaz el procedimiento

que permita solicitar esa copia, siendo desarrollado luego por las clases concretas del patrón

que deseen crear ese clon.

Como podemos ver, la principal razón de uso de este patrón de diseño software de creación

es crear las distintas clases de objetos que necesite el sistema, y hacerlo en el momento y

entorno adecuados. Eso sí, la lógica y diseño que necesite el sistema para la ejecución y

decisión de la creación de estos objetos copia, se hace de forma independiente al patrón,

siendo éste referido cuando el fragmento de código pertinente solicite una copia del objeto

que necesite. Cabe destacar que hacer una 'copia' significa crear otra instancia del objeto

(siempre que este tenga la funcionalidad de clonarse) con las particularidades necesarias en

ese instante.

Page 21: Factory Method

Desacar también, que el API de Java dispone de interfaz Cloneable que facilita la

implementación de este patrón, haciéndola compatible con otros prototipos que se

encuentran en las diferentes librerías de Java.

Este sería el diagrama de clases general del patrón:

Esquema del patrón Prototype

Visto esto, los actores que intervienen en el patrón de creación Prototype, son:

Cliente:  actor solicitante de la creación (clonación) de los nuevos objetos a partir de los prototipos.

Prototipo Concreto:  actor (clase) que presenta unas características concretas que serán reproducidas en los nuevos objetos y que presenta la implementación necesaria para clonarse.

Prototipo:  declara una interfaz, al a que accede el cliente, que sirve para la clonación de objetos.

En este enlace podrá consultar un código de ejemplo en Java del patrón de creación

Prototype.

Singleton

El patrón de diseño de software de creación Singleton (haciendo referencia a una instancia

única) busca restringir la creación de objetos pertenecientes a una clase o el valor de un tipo

a un único objeto. Su intención es garantizar que una clase sólo sea instanciada una vez y,

Page 22: Factory Method

además, proporcionar un único punto de acceso global a la misma. Esto lo consigue gracias a

que es la propia clase la responsable de crear esa única instancia, (declarando el constructor

de la clase como privado) y a que se permite el acceso global a dicha instancia mediante un

método de clase.

Para implementar el patrón singleton hay que crear un método que instancie al objeto sólo

si todavía no existe ninguna otra instancia. Para asegurar que no vuelva a ser instanciado, se

limita al constructor con atributos protegidos o privados. Por esto, la implementación del

patrón puede ser complicada en programas multihilo, ya que si dos o más hilos de ejecución

instanciaran la clase al mismo tiempo sólo uno de ellos debería lograr crear el objeto. La

solución clásica para este problema es utilizar exclusión mutua en el método de creación de

la clase que implementa el patrón. Ejemplos de situaciones habituales en las que convendría

aplicar este ejemplo de patrón de diseño son aquellas en las que la clase principal busca

controlar el acceso a un recurso único (como puede ser el ratón o un archivo abierto en modo

exclusivo) o cuando cierto tipo de datos debe estar disponible para todos los demás objetos.

Este sería el diagrama de clases general del patrón de creación Singleton:

Abstract FactoryEste patrón crea diferentes familias de objetos. Su objetivo principal es soportar múltiples estándares que vienen definidos por las diferentes jerarquías de herencia de objetos. Es similar al Factory Method, sólo que esta orientado a combinar productos.

Se debe utilizar este patrón cuando: Un sistema se debe configurar con una de entre varias familias de productos.

Una familia de productos relacionados están hechos para utilizarse juntos.

Diagrama UML

Page 23: Factory Method

AbstractFactory: declara una interfaz para la creación de objetos de productos abstractos.ConcreteFactory: implementa las operaciones para la creación de objetos de productos concretos.AbstractProduct: declara una interfaz para los objetos de un tipo de productos.ConcreteProduct: define un objeto de producto que la correspondiente factoría concreta se encargaría de crear, a la vez que implementa la interfaz de producto abstracto.Client: utiliza solamente las interfaces declaradas en la factoría y en los productos abstractos. Una única instancia de cada FactoryConcreto es creada en tiempo de ejecución. AbstractFactory delega la creación de productos a sus subclases FactoryConcreto.

Ahora que explique que rol ocupa cada uno en el diagrama, les pido un poco de atención en lo siguiente: veamos que relación tienen  los FactoryConcretos con respectos a los productos. Esto es, FactoryConcreto1 crea una relación entre un producto de la familia A y un producto de la familia B. Y, por otro lado, tenemos que el FactoryConcreto2 crea una relación entre otros dos productos de ambas familias.Esto ya debería darnos una pista sobre el funcionamiento del AbstractFactory: se crea una clase por cada relación que necesitemos crear. Esto quedará más claro en el ejemplo a continuación.

Ejemplo

Hagamos de cuenta que tenemos dos familias de objetos:1) La clase TV, que tiene dos hijas: Plasma y LCD.2) La clase Color, que tiene dos hijas: Amarillo y Azul (los mejores colores, sin duda! ).

Más alla de todos los atributos/métodos que puedan tener la clase Color y TV, lo importante aquí es destacar que Color define un método abstracto:  public abstract void colorea(TV tv);

Este método es la relación que une las dos familias de productos.Dado que es un método

Page 24: Factory Method

abstracto, Azul debe redefinirlo:

public void colorea(TV tv) {System.out.println("Pintando de azul el "+ tv.getDescripcion());}

Lo mismo ocurre con Amarillo:

public void colorea(TV tv) {System.out.println("Pintando de amarillo el "+ tv.getDescripcion());}

Bien, veamos las clases correspondientes antes de continuar con nuestros ejemplo.

Page 26: Factory Method

Escenario: nuestra empresa se dedica a darle un formato estético específico a los televisores LCD y Plasma. Se ha decidido que todos los LCD que saldrán al mercado serán azules y los plasma serán amarillos. Ahora bien, una solución simple sería en la clase Azul colocar el LCD y en la clase Amarillo colocar el Plasma y todo funcionaría de maravillas. ¿Cual sería el problema? Que esta todo hardcodeado. Esto quiere decir que el hecho de que los LCD sean azules y los plasmas amarillos es una decisión del negocio y, como tal, puede variar (y de hecho el negocio varía constantemente).Por ejemplo, que pasa si mañana Se agrega otro color o me cambian el color del LCD o mucho peor, ¿que pasa si se crea otro producto LED y también se lo quiere pintar de Azul?Para evitar un dolor de cabeza conviene separar estas familias y utilizar el Abstract Factory:

Page 28: Factory Method

Consecuencias Se oculta a los clientes las clases de implementación: los clientes manipulan los objetos a través de las interfaces o clases abstractas.

Facilita el intercambio de familias de productos: al crear una familia completa de objetos con una factoría abstracta, es fácil cambiar toda la familia de una vez simplemente cambiando la factoría concreta.

Mejora la consistencia entre productos: el uso de la factoría abstracta permite forzar a utilizar un conjunto de objetos de una misma familia.

Como inconveniente podemos decir que no siempre es fácil soportar nuevos tipos de productos si se tiene que extender la interfaz de la Factoría abstracta.

Ejemplo Patrón Abstract Factory

Siguiendo con la secuencia de entradas sobre patrones de diseño, en esta ocasión realizaremos un ejemplo usando el Patrón Abstract Factory.......... es uno de esos ejemplos simples pero que enmarcan el objetivo del patrón.......

Que es?

Antes que nada debemos saber que existe un patrón llamado Factory el cual permite delegar en una clase la responsabilidad de crear objetos de otras clases, basados en esto Podemos decir que el Abstract Factoryes una nueva fase de Factory, Teniendo así una

Page 29: Factory Method

Fabrica de Objetos donde la creación es transparente para la clase que los solicita.

Debemos saber entonces que el patrón Abstract Factory nos brinda una interfaz para crear familias de Objetos relacionados sin tener que especificar sus clases concretas desde la clase cliente (Clase que los solicita)

El problema

Se solicita la creación de diferentes vehículos de transporte (Buses, Busetas y Taxis) sin que se especifique en detalle la forma de su creación.

La solución.

Utilizamos el patrón Abstract Factory para independizar la forma como crearemos los objetos, de esta manera creamos familias de objetos de tipo Vehículo delegando el proceso y sin tener que entrar en detalles desde la clase solicitante.

 

La Aplicación.

Una vez mas trabajamos con un ejemplo simple, veremos una aplicación pequeña que permite al usuario crear  familias de vehículos de 3 tipos diferentes, Buses, Busetas y Taxis, tan solo presentamos unas opciones de selección donde escogeremos que Objeto crear, he internamente  por medio del Patrón de Diseño ejecutamos el proceso de creación....

Con este patrón revivimos Conceptos Básicos de Programación Orientada a Objetos tales como Las Interfaces, métodos Abstractos, Herencia, polimorfismo entre otros (si no los conocen los invito a darles una mirada aquí)... 

Page 30: Factory Method

En General la Aplicación se divide en Clases Fabricas que permiten hacer el llamado a la creación de Objetos, Interfaces que permiten aplicar conceptos como la Herencia y elPolimorfismo, también contamos con clases Concretas que representan los Objetos que crearán las Fabricas y por ultimo la clase principal que permitirá delegar las solicitudes para iniciar el proceso de creación.... Veamos!!!

Las Interfaces. 

Interface Vehiculo.

Esta Interface es común para todos los vehículos de nuestra fabrica, en ella se declaran 2 métodos abstractos que serán comunes para los objetos a crear, sin importar si son Buses, Busetas o Taxis (Sabemos que por regla todos los métodos de una interfaz son abstractos, por ello no es necesario declararlos como tal) 

1

2

3

4

5

6

7

package interfaces;

/**

 * interfaz donde se establece el codigo del servicio

 * @author chenao

 */

public interface Vehiculo

{

Page 31: Factory Method

8

9

10

11

 public void codigoDeVehiculo();

 public int generarCodigo();

}

Interface VehiculoDeTransporte.

Esta Interface será implementada por las diferentes fabricas de de vehículos de la aplicación, cuenta con el método abstracto crearVehiculo() que será común para cada fabrica y como su nombre lo dice, le permitirá a cada una implementar la lógica para crear sus objetos concretos.

1

2

3

4

5

6

7

8

9

package interfaces;

/**

 * interfaz que establece la creacion de un servicio

 * @author chenao

 */

public interface VehiculoDeTransporte {

 public Vehiculo crearVehiculo();

}

Las Fabricas.

Se componen por la Fabrica de Vehículos Principal que hace el llamado a las fabricas de Objetos Concretos..... estas implementan la interface VehiculoDeTransporte permitiendo crear los vehículos del tipo correspondiente y asignar el respectivo código de creación..... 

Clase FabricaDeVehiculos.

Esta clase sera la Fabrica Principal cuenta con un método estático que permitirá la creación de los diferentes tipos de vehículos, aplicamos el concepto de polimorfismo para ejecutar el llamado a la Fabrica correspondiente y crear el objeto concreto solicitado  por el cliente.

Page 32: Factory Method

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

package fabricas;

import interfaces.Vehiculo;

import interfaces.VehiculoDeTransporte;

/**

 * Clase que permite la creacion de un servicio

 * @author chenao

 *

 */

public class FabricaDeVehiculos {

 public static void crearFabricaDeVehiculo(VehiculoDeTransporte factory){

  /**Aplicamos Polimorfismo*/

  Vehiculo objetoVehiculo= factory.crearVehiculo();

  objetoVehiculo.codigoDeVehiculo();

 }

}

Clase FabricaBuses.

1

2

3

4

5

6

7

8

package fabricas;

import interfaces.Vehiculo;

import interfaces.VehiculoDeTransporte;

import javax.swing.JOptionPane;

import clases.Bus;

/**

Page 33: Factory Method

9

10

11

12

13

14

15

16

17

18

19

20

21

 * Clase que permite la creacion de un objeto Bus

 * @author chenao

 *

 */

public class FabricaBuses implements VehiculoDeTransporte{

  public Vehiculo crearVehiculo() {

  Bus miBus=new Bus();

  miBus.setCodigo(miBus.generarCodigo());

  JOptionPane.showMessageDialog(null, "Se ha creado un nuevo Objeto Bus  ");

  return miBus;

 }

}

Clase FabricaBusetas.

1

2

3

4

5

6

7

8

9

10

11

12

package fabricas;

import interfaces.Vehiculo;

import interfaces.VehiculoDeTransporte;

import javax.swing.JOptionPane;

import clases.Buseta;

/**

 * Clase que permite la creacion de un objeto Buseta

 * @author chenao

 *

 */

Page 34: Factory Method

13

14

15

16

17

18

19

20

21

22

public class FabricaBusetas implements VehiculoDeTransporte{

 @Override

 public Vehiculo crearVehiculo() {

  Buseta miBuseta=new Buseta();

  miBuseta.setCodigo(miBuseta.generarCodigo());

 JOptionPane.showMessageDialog(null, "Se ha creado un nuevo Objeto Buseta");

  return miBuseta;

 }

}

Clase FabricaTaxis.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

package fabricas;

import interfaces.Vehiculo;

import interfaces.VehiculoDeTransporte;

import javax.swing.JOptionPane;

import clases.Taxi;

/**

 * Clase que permite la creacion de un objeto Taxi

 * @author chenao

 *

 */

public class FabricaTaxis implements VehiculoDeTransporte{

 @Override

 public Vehiculo crearVehiculo() {

  Taxi miTaxi=new Taxi();

Page 35: Factory Method

16

17

18

19

20

21

22

  miTaxi.setCodigo(miTaxi.generarCodigo());

  JOptionPane.showMessageDialog(null, "Se ha creado un nuevo Objeto Taxi");

  return miTaxi;

 }

}

Las Clases Concretas. 

Representan las clases de las que se instanciarán los objetos de tipo Vehículo (Buses, Busetas y Taxis) así como la clase principal que permite delegar las funcionalidades.....Las clases Bus, Buseta y Taxi Implementan la Interface Vehículo, y cada una permite generar un código aleatorio para identificar el vehículo creado....

Clase Bus.

1

2

3

4

5

6

7

8

9

10

11

12

13

package clases;

import interfaces.Vehiculo;

import javax.swing.JOptionPane;

/**

 *  clase que establece el codigo del servicio de buses

 * @author chenao

 *

 */

public class Bus implements Vehiculo{

 private int codigo;

 public int generarCodigo()

Page 36: Factory Method

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

 {

  int codigoBus=(int) (Math.random()*9999);

  return codigoBus;

 }

 public int getCodigo() {

  return codigo;

 }

 public void setCodigo(int codigo) {

  this.codigo = codigo;

 }

 public void codigoDeVehiculo() {

  JOptionPane.showMessageDialog(null,"El Codigo del Bus es : "+getCodigo());

 }

}

Clase Buseta.

1

2

3

4

5

6

7

8

9

10

package clases;

import interfaces.Vehiculo;

import javax.swing.JOptionPane;

/**

 *  clase que establece el codigo del servicio de busetas

 * @author chenao

 */

public class Buseta implements Vehiculo{

Page 37: Factory Method

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

 private int codigo;

 public int generarCodigo()

 {

  int codigoBuseta=(int) (Math.random()*9999);

  return codigoBuseta;

 }

 public int getCodigo() {

  return codigo;

 }

 public void setCodigo(int codigo) {

  this.codigo = codigo;

 }

 @Override

 public void codigoDeVehiculo() {

JOptionPane.showMessageDialog(null,"El Codigo de la Buseta es:"+getCodigo());

 }

}

Clase Taxi. 

1

2

3

4

5

6

7

package clases;

import interfaces.Vehiculo;

import javax.swing.JOptionPane;

/**

 * clase que establece el codigo del servicio de taxis

 * @author chenao

 */

Page 38: Factory Method

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

public class Taxi implements Vehiculo{

 private int codigo;

 public int generarCodigo()

 {

  /**Generamos un codigo aleatorio para el taxi*/

  int codigoTaxi=(int) (Math.random()*9999);

  return codigoTaxi;

 }

 public int getCodigo() {

  return codigo;

 }

 public void setCodigo(int codigo) {

  this.codigo = codigo;

 }

 @Override

 public void codigoDeVehiculo() {

  JOptionPane.showMessageDialog(null,"El Codigo del Taxi es : "+getCodigo());

 }

}

Clase Principal. 

Esta clase permite iniciar el sistema, en ella creamos las instancias de Fabricas y mediante un menú de opciones se define y delega que Fabrica inicia el proceso de creación...

1

2

package principal;

import javax.swing.JOptionPane;

Page 39: Factory Method

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

import fabricas.FabricaBuses;

import fabricas.FabricaBusetas;

import fabricas.FabricaDeVehiculos;

import fabricas.FabricaTaxis;

/**

 * clase principal del aplicativo donde se establecen las instancias

 * de las fabricas

 * @author chenao

 *

 */

public class Principal {

public static void main(String[] args)

{

 FabricaBusetas busetas=new FabricaBusetas();

 FabricaTaxis taxi=new FabricaTaxis();

 FabricaBuses buses=new FabricaBuses();

 String cad="",salida;

cad+="Ingrese la opción correspondiente para obtener el codigo del servicio\n";

 cad+="1. Codigo servicio de Taxis\n";

 cad+="2. Codigo servicio de Buses\n";

 cad+="3. Codigo servicio de Busetas\n\n";

 try {

 do {

  try

     {

  int opcion=Integer.parseInt(JOptionPane.showInputDialog(cad));

Page 40: Factory Method

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

  switch (opcion)

  {

  case 1:FabricaDeVehiculos.crearFabricaDeVehiculo(taxi);

   break;

 case 2:FabricaDeVehiculos.crearFabricaDeVehiculo(buses);

   break;

 case 3:FabricaDeVehiculos.crearFabricaDeVehiculo(busetas);

   break;

default:JOptionPane.showMessageDialog(null,"No es un valor de consultavalido");

    break;

   }

  } catch (Exception e) {

 JOptionPane.showMessageDialog(null,"No es un parametro de consulta valido");

  }

 salida=JOptionPane.showInputDialog("Desea consultar otro codigo? S/N");

 } while (salida.toUpperCase().equals("S"));

     } catch (Exception e) {

  JOptionPane.showMessageDialog(null,"Bye!!!");

  }

 }

}

Conclusiones.

Y Listo!!! Como vemos  es un Patrón que al principio puede sonar un poco intimidante pero a medida que vamos trabajando con el nos damos

Page 41: Factory Method

cuenta de como podemos sacarle provecho a su aplicación...

Podemos evidenciar también el uso de varios conceptos de programación orientada a objetos siendo los patrones de diseño un gran ejemplo de su aplicación....

Page 42: Factory Method

Programa para resolver ecuaciones lineales por los metodos de Jacobi o de Gauss-Seidel

function metodo=metodo()format longdisp('¿QUE METODO DESEA UTILIZAR PARA RESOLVER EL PROBLEMA?');disp('1.-MÉTODO DE JACOBI');disp('2.-MÉTODO DE GAUSS');disp('3.-SALIR');n=input('SELECCIONE UNA OPCION: ');if n==1num=input('INTODUCE EL NUMERO DE ECUACIONES: ');A=input('INTRODUCE LA MATRIZ DE COEFICIENTES: ');b=input('INTRODUCE LA MATRIZ DE COEFICIENTES INDEPENDIENTES: ');z=input('INTRODUZCA EL NUMERO DE ITERACIONES: ');X0=zeros(1,num);for f=1:zfor i=1:numsuma=0;for j=1:numif i~=jsuma=suma+A(i,j)*X0(j);endendX(i)=(b(i)-suma)/A(i,i);fprintf('%10.4f',X(i));endfprintf('\n');X0=X;endelseif n==2num=input('INTRODUCE EL NUMERO DE ECUACIONES: ');A=input('INTRODUCE LA MATRIZ DE COEFICIENTES: ');b=input('INTRIODUCE LA MATRIZ DE COEFICIENTES INDEPENDIENTES: ');z=input('INTRODUZCA EL NUMERO DE ITERACIONES: ');X0=zeros(1,num);X=X0;for f=1:zfor i=1:numsuma=0;for j=1:numif i~=jsuma=suma+A(i,j)*X(j);endendX(i)=(b(i)-suma)/A(i,i);fprintf('%10.4f', X(i));endX0=X;

Page 43: Factory Method

fprintf('\n');endelseif n==3return;elsedisp('ERROR');end

MÉTODO DE JACOBI y MÉTODO DE GAUSS-SEIDELPara el método de Jacobi, considere un sistema Ax=b

Sea A = D - E - F, donde D es la diagonal de A, -E la triangula inferior y -F la

triangular superior.Así, la sucesión que se construye con este método iterativo será:Ax = b(D-E-F)x = b Dx = (E+F)x + b

x(k) = D-1(E+F)x(k-1) + D-

1bEl siguiente programa resuelve mediante el método de Jacobi un sistema de ecuaciones Ax=b con un error menor que una tolerancia dada tol. Note que el programa necesita un dato inicial x0. Además, el programa se detiene si se alcanza un número máximo de iteraciones maxit sin que se satisfaga el criterio de convergencia.

function [x,iter]=jac(A,b,x,tol,maxit)

N=diag(diag(A));

P=N-A; corr=1; errest=1; iter=0;

while abs(errest)>tol & iter<maxit

    iter=iter+1;

    x0=x;

    corr0=corr;

    x=N\(P*x0+b);

    corr=norm(x-x0,inf);

    normest=corr/corr0;

    if normest>=1 & iter>=2

       error('norma de la matriz de iteración > 1')

    end

Page 44: Factory Method

    errest=normest/(1-normest)*corr; 

end

iter

Ejemplo: Resuelva Ax(0)=b, con una aproximación inicial x(0)=[0 0 0]'

>> A=[5 -2 1;-1 -7 3;2 -1 8];>> x=[0 0 0]';>> b=[3 -2 1]';>> tol=10^-6;>> maxit=200;>> jac(A,b,x,tol,maxit)

iter=

        13

ans=

        0.6763

        0.1799

       -0.0216

Para el MÉTODO DE GAUSS-SEIDEL, modificar N y P:N=tril(A)P=N-A 

Codigo Jacobi   Matlab Publicado en 26 enero, 2010de dgm116

function[]=jacobi(y,v)

%funcion que soluciona un sistema de ecuaciones simultaneas 

[r,c]=size(y);%r guarda el numero de renglones y c el numero de columnas

d=diag(y);%d sera un vector el cual contendra los elementos de la 

          %diagonal principal de la matriz formada por el sistema 

Page 45: Factory Method

          %de ecuaciones

h=0;%h servira de contador

z=0;%z sera el valor que usaremos para condicionar

k=0;

for i=1:r%Inicio de despeje de incognitas

    for j=1:c

        if j~=i

            x(i,j)=[-y(i,j)./d(i)];%x sera una matriz la cual contendra

                                   %en sus renglones nuestras incognitas 

                                   %despejadas 

        end

    end

end %incognitas despejadas

while z~=1%ciclo que se repetira hasta encontrar el valor de las incognitas

    for i=1:r%este ciclo nos servira para controlar el numero de 

             %renglon en que se este analizando y asi evaluar las

             %incognitas

             %despejadas y obtener los nuevos valores que se utilizaran

             %para evaluar dichas incognitas

        f(i)=0;%la posicion i del vector f se le asignara cero 

               %para evitar una acomulacion

        for j=1:c%ciclo que nos servira para encontrar los nuevos valores 

                 %en los que se evaluara nuestras incognitas

            if j~=c%condicion para evitar multiplicar el valor constante 

               f(i)=f(i)+(x(i,j).*v(j));%el vector f tomara los nuevos 

                                        %valores en los se volveran a

                                        %evaluar las incognitas despejadas

            else

               f(i)=f(i)+(x(i,j));

            end

        end

    end

    for i=1:r

        if f(i)==v(i)%se comparan los valores del vector f con los 

                     %del vector v

            h=h+1;%si se cumple la condicion el contador aumenta

        end

    end

Page 46: Factory Method

    for i=1:r

        v(i)=f(i);%el vector v adquiere los nuevos valores obtenidos 

                  %anteriormente

    end

    if h==r

        z=1;%si el contador es igual al numero de renglones quiere decir

            %que los valores utilizados anteriormente son iguales a los

            %acabados de obtener

    else

        h=0;%si no el contador regresa a cero

    end