Patrones de diseño

  • 8 Respuestas
  • 5632 Vistas

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Gus Garsaky

  • *
  • Underc0der
  • Mensajes: 93
  • Actividad:
    0%
  • Reputación -1
  • Skype: gus.garsaky
    • Ver Perfil

Patrones de diseño

  • en: Abril 26, 2015, 08:31:32 pm

PATRONES DE DISEÑO


CAPÍTULO I

Introducción

Los patrones de diseño son la base para la búsqueda de soluciones a problemas comunes en el desarrollo de software y otros ámbitos referentes al diseño de interacción o interfaces.
Un patrón de diseño resulta ser una solución a un problema de diseño. Para que una solución sea considerada un patrón debe poseer ciertas características. Una de ellas es que debe haber comprobado su efectividad resolviendo problemas similares en ocasiones anteriores. Otra es que debe ser reutilizable, lo que significa que es aplicable a diferentes problemas de diseño en distintas circunstancias.

Los patrones de diseño pretenden:

  • Proporcionar catálogos de elementos reusables en el diseño de sistemas software. [/li]
  • Evitar la reiteración en la búsqueda de soluciones a problemas ya conocidos y solucionados anteriormente. [/li]
  • Formalizar un vocabulario común entre diseñadores. [/li]
  • Estandarizar el modo en que se realiza el diseño. [/li]
  • Facilitar el aprendizaje de las nuevas generaciones de diseñadores condensando conocimiento ya existente.[/li][/list]

    Asimismo, no pretenden:

  • Imponer ciertas alternativas de diseño frente a otras. [/li]
  • Eliminar la creatividad inherente al proceso de diseño. [/li][/list]

    No es obligatorio utilizar los patrones, solo es aconsejable en el caso de tener el mismo problema o similar que soluciona el patrón, siempre teniendo en cuenta que en un caso particular puede no ser aplicable. "Abusar o forzar el uso de los patrones puede ser un error".


    PATRÓN ADAPTER


    El patrón adapter nos permite ampliar la funcionalidad de una clase o interfaz adaptando objetos que no coinciden con una determinada jerarquía de clases.

    Convierte la interfaz de una clase en otra interfaz que el cliente espera. Adapter permite a las clases trabajar juntas, lo que de otra manera no podría hacerlo debido a sus interfaces incompatibles.

    Cuándo usarlo:

  • Se desea usar una clase existente, y su interfaz no se iguala con la necesitada. [/li]
  • Cuando se desea crear una clase reusable que coopera con clases no relacionadas, es decir, las clases no tienen necesariamente interfaces compatibles.[/li]


    Problema: Se nos pide adaptar un auto eléctrico a un sistema de abastecimiento de combustible para autos. Siendo que el auto eléctrico, utiliza como combustible la energía eléctrica.

    Solución: Utilizar el patrón Adapter para extender la funcionalidad de la interfaz adaptando el auto eléctrico.

    Creamos una interfaz llamada Car que representará de forma genérica a un Auto:

    Car.java
    Código: Java
    1. package org.underc0de.adapter;
    2.  
    3. public interface Car {
    4.  
    5.    void fillTank();
    6.    default void start() {
    7.       You are not allowed to view links. Register or Login.out.println("Encendiendo auto...");
    8.    }
    9. }

    NOTA: el método start() lo predefinimos porque será el mismo para todos las implementaciones.

    Ahora sus implementaciones: GasolineCar y GasCar. Representan un auto a gasolina y otro a gas.

    GasolineCar.java
    Código: Java
    1. package org.underc0de.adapter;
    2.  
    3. public class GasolineCar implements Car {
    4.  
    5.    public GasolineCar() {
    6.       super(); // llamada al constructor padre
    7.       You are not allowed to view links. Register or Login.out.println("Creando un auto a gasolina...");
    8.    }
    9.    
    10.    @Override
    11.    public void fillTank() {
    12.       You are not allowed to view links. Register or Login.out.println("Colocando gasolina...");
    13.    }
    14. }
    15.  

    GasCar.java
    Código: Java
    1. package org.underc0de.adapter;
    2.  
    3. public class GasCar implements Car {
    4.  
    5.    public GasCar() {
    6.       super(); // llamada al constructor padre
    7.       You are not allowed to view links. Register or Login.out.println("Creando un auto a gas...");
    8.    }
    9.    
    10.    @Override
    11.    public void fillTank() {
    12.       You are not allowed to view links. Register or Login.out.println("Colocando gas...");
    13.    }
    14.  
    15. }

    Ambos autos, GasolineCar y GasCar necesitan combustible para funcionar. Por eso, el método fillTank llena el combustible de ellos, dependiendo si es gasolina o gas.

    Ahora queremos añadir un auto eléctrico a nuestra jerarquía de clases.

    ElectricCar.java
    Código: Java
    1. package org.underc0de.adapter;
    2.  
    3. public class ElectricCar {
    4.  
    5.    public ElectricCar() {
    6.       super(); // llamada al constructor padre
    7.       You are not allowed to view links. Register or Login.out.println("Creando un auto eléctrico...");
    8.    }
    9.    
    10.    public void connect() {
    11.       You are not allowed to view links. Register or Login.out.println("Conectando motor a generador de electricidad...");
    12.    }
    13. }

    Nos damos con la sorpresa que éste auto no coincide con nuestra jerarquía. La interfaz Car dice que todos los autos que la implementen deben tener el método fillTank. Pero, ¿Como un auto eléctrico puede llenar el tanque? ¿Cómo hacemos para adaptar éste auto a nuestra jerarquía?

    Un error es común es modificar la interfaz o clase abstracta. Ésto viola el principio OCP, el cual nos dice:
    Citar
    Las entidades de software deben ser abiertas para ser extendidas y cerradas para no ser modificadas.

    Aquí toma importancia en patrón Adapter. Éste patrón nos permite ampliar la funcionalidad de una interfaz si tener que cambiar código en ella. Veamos como funciona.

    Código: Java
    1. package org.underc0de.adapter;
    2.  
    3. public class ElectricCarAdapter implements Car {
    4.  
    5.    ElectricCar electricCar;
    6.    
    7.    public ElectricCarAdapter() {
    8.       electricCar = new ElectricCar();
    9.    }
    10.    
    11.    @Override
    12.    public void fillTank() {
    13.       electricCar.connect();
    14.      
    15.    }
    16.  
    17. }

    Como vemos hemos podido adaptar nuestro auto eléctrico a nuestra interfaz Car. ¡Ahora, podemos crear tanto autos a gasolina, gas o eléctricos aplicando polimorfismo!

    Veamos que salida nos arroja:

    AdapterTest.java
    Código: Java
    1. package org.underc0de.adapter;
    2.  
    3. public class AdapterTest {
    4.  
    5.    public static void main(You are not allowed to view links. Register or Login[] args) {
    6.       Car gasolineCar = new GasolineCar();
    7.       gasolineCar.fillTank();
    8.       gasolineCar.start();
    9.      
    10.       You are not allowed to view links. Register or Login.out.println();
    11.      
    12.       Car gasCar = new GasCar();
    13.       gasCar.fillTank();
    14.       gasCar.start();
    15.      
    16.       You are not allowed to view links. Register or Login.out.println();
    17.      
    18.       Car electricCar = new ElectricCarAdapter();
    19.       electricCar.fillTank();
    20.       electricCar.start();
    21.    }
    22.  
    23. }

    Salida:

    Código: You are not allowed to view links. Register or Login
    Creando un auto a gasolina...
    Colocando gasolina...
    Encendiendo auto...

    Creando un auto a gas...
    Colocando gas...
    Encendiendo auto...

    Creando un auto eléctrico...
    Conectando motor a generador de electricidad...
    Encendiendo auto...

    Y así podemos extender la funcionalidad de nuestra aplicación de forma sencilla y eficiente.


    PATRÓN FACADE


    Descripción: El patrón fachada viene motivado por la necesidad de estructurar un entorno de programación y reducir su complejidad con la división en subsistemas, minimizando las comunicaciones y dependencias entre éstos.

    Cuándo usarlo:

  • Se usa para proporcionar una interfaz sencilla para un sistema complejo. [/li]
  • Se quiere desacoplar un subsistema de sus clientes u otros subsistemas, haciéndolo mas independiente y portable. [/li]
  • Se quiera dividir los sistemas en niveles: las fachadas serian el punto de entrada a cada nivel.[/li]

    Pros/contras:

  • + La principal ventaja del patrón fachada consiste en que para modificar las clases de los subsistemas, sólo hay que realizar cambios en la interfaz/fachada, y los clientes pueden permanecer ajenos a ello. Además, y como se mencionó anteriormente, los clientes no necesitan conocer las clases que hay tras dicha interfaz.[/li]
  • - Como inconveniente, si se considera el caso de que varios clientes necesiten acceder a subconjuntos diferentes de la funcionalidad que provee el sistema, podrían acabar usando sólo una pequeña parte de la fachada, por lo que sería conveniente utilizar varias fachadas más específicas en lugar de una única global.[/li]

    Problema: Crear una aplicación que haga tres operaciones bancarias: Crear una cuenta, depositar dinero y retirar dinero. Las operaciones deben hacerse dentro de una sola entidad que las maneje.

    Solución: Aplicar el patrón Facade para encapsular todos los objetos que hacen las 3 operaciones.

    Bank.java
    Código: Java
    1. package org.underc0de.facade;
    2.  
    3. public class Bank {
    4.  
    5.    public Bank() {
    6.      
    7.    }
    8.    
    9.    public void createAccount(You are not allowed to view links. Register or Login account) {
    10.       You are not allowed to view links. Register or Login.out.println("Creando cuenta N° "+account);
    11.    }
    12. }

    Deposit.java
    Código: Java
    1. package org.underc0de.facade;
    2.  
    3. public class Deposit {
    4.  
    5.    public Deposit() {
    6.      
    7.    }
    8.    
    9.    public void makeDeposit(double amount, You are not allowed to view links. Register or Login account) {
    10.       You are not allowed to view links. Register or Login.out.println("Se ha depositado $"+amount+" a la cuenta "+account);
    11.    }
    12.    
    13. }

    Withdrawal.java
    Código: Java
    1. package org.underc0de.facade;
    2.  
    3. public class Withdrawal {
    4.  
    5.    public Withdrawal() {
    6.      
    7.    }
    8.    
    9.    public void makeWidthdrawal(double amount, You are not allowed to view links. Register or Login account) {
    10.       You are not allowed to view links. Register or Login.out.println("Se ha retirado $"+amount+" de la cuenta "+account);
    11.    }
    12.    
    13. }

    Ahora, creamos nuestra clase principal:

    FacadeTest.java
    Código: Java
    1. package org.underc0de.facade;
    2.  
    3. public class Facade {
    4.  
    5. public static void main(You are not allowed to view links. Register or Login[] args) {
    6.  
    7.    Bank bank = new Bank();
    8.    Deposit deposit = new Deposit();
    9.    Withdrawal withdrawal = new Withdrawal();
    10.      
    11.    bank.createAccount("9343435093");
    12.    deposit.makeDeposit(2599.90, "9343435093");
    13.    withdrawal.makeWidthdrawal(699.90, "9343435093");
    14.          
    15.    }
    16.  
    17. }

    Como vemos creamos 3 objetos los cuales se encargan de efectuar las acciones. Pero, ¿es necesario crear éstos tres objetos en éste ambito? ¿Los vamos a necesitar siempre?

    Una mejor idea sería encapsular éstos objetos dentro de uno solo que se encargue de realizar todas las operaciones. Éste es el propósito del patrón Facade, actuar como intermediario entre la interfaz y las funcionalidades de un sistema. Veamos como se representa:

    OperationsFacade.java
    Código: Java
    1. package org.underc0de.facade;
    2.  
    3. public class OperationsFacade {
    4.  
    5.    
    6.    public OperationsFacade() {
    7.    }
    8.    
    9.    public void createAccount(You are not allowed to view links. Register or Login account) {
    10.       new Bank().createAccount(account);
    11.    }
    12.    
    13.    public void makeDeposit(double amount, You are not allowed to view links. Register or Login account) {
    14.       new Deposit().makeDeposit(amount, account);
    15.    }
    16.    
    17.    public void makeWithdrawal(double amount, You are not allowed to view links. Register or Login account) {
    18.       new Withdrawal().makeWidthdrawal(amount, account);
    19.    }
    20.    
    21. }

    Como podemos observar, ésta clase encapsula el comportamiento de las clases Bank, Deposit y Withdrawal. Ya no tenemos que declarar los objetos porque éstos se crean en los métodos de OperationsFacade y se destruyen al finalizar el mismo. ¡Además ahorramos memoria!

    Ahora, veamos como queda la clase principal:

    FacadeTest.java
    Código: Java
    1. package org.underc0de.facade;
    2.  
    3. public class FacadeTest {
    4.  
    5.    public static void main(You are not allowed to view links. Register or Login[] args) {
    6.       OperationsFacade facade = new OperationsFacade();
    7.       facade.createAccount("9343435093");
    8.       facade.makeDeposit(2599.90, "9343435093");
    9.       facade.makeWithdrawal(699.90, "9343435093");
    10.    }
    11.  
    12. }

    Como podemos ver, solo necesitamos de un objeto OperationsFacade para realizar todas las operaciones. Así aplicamos también el principio KISS (Keep it simple stupid!).

    Salida:

    Código: You are not allowed to view links. Register or Login
    Creando cuenta N° 9343435093
    Se ha depositado $2599.9 a la cuenta 9343435093
    Se ha retirado $699.9 de la cuenta 9343435093


    PATRÓN ABSTRACT FACTORY


    Descripción: 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.

    Cuándo usarlo:

  • Un sistema debe ser independiente de como sus objetos son creados. [/li]
  • Un sistema debe ser 'configurado' con una cierta familia de productos. [/li]
  • Se necesita reforzar la noción de dependencia mutua entre ciertos objetos. [/li]


    Pros/contras:

  • + Brinda flexibilidad al aislar a las clases concretas. [/li]
  • + Facilita cambiar las familias de productos. [/li]
  • - Para agregar nuevos productos se deben modificar tanto las fabricas abstractas como las concretas. [/li]

    Problema: Se nos pide crear animales de X tipo sin especificar cuál es el objeto en concreto.

    Solución: Utilizar el patrón Abstract Factory para crear los objetos solicitados.

    Primero, creamos una clase abstracta llamada Animal que representará de forma genérica a un Animal:

    Animal.java
    Código: Java
    1. package org.underc0de.factory;
    2.  
    3. public abstract class Animal {
    4.  
    5.    protected You are not allowed to view links. Register or Login type;
    6.    protected You are not allowed to view links. Register or Login family;
    7.    protected You are not allowed to view links. Register or Login habitat;
    8.    
    9.    public Animal(You are not allowed to view links. Register or Login type, You are not allowed to view links. Register or Login family, You are not allowed to view links. Register or Login habitat) {
    10.       this.type = type;
    11.       this.family = family;
    12.       this.habitat = habitat;
    13.    }
    14.    
    15.    public You are not allowed to view links. Register or Login getType() {
    16.       return type;
    17.    }
    18.    
    19.    public void setType(You are not allowed to view links. Register or Login type) {
    20.       this.type = type;
    21.    }
    22.  
    23.    public You are not allowed to view links. Register or Login getFamily() {
    24.       return family;
    25.    }
    26.  
    27.    public void setFamily(You are not allowed to view links. Register or Login family) {
    28.       this.family = family;
    29.    }
    30.  
    31.    public You are not allowed to view links. Register or Login getHabitat() {
    32.       return habitat;
    33.    }
    34.  
    35.    public void setHabitat(You are not allowed to view links. Register or Login habitat) {
    36.       this.habitat = habitat;
    37.    }
    38.  
    39.    @Override
    40.    public You are not allowed to view links. Register or Login toString() {
    41.       return "Tipo de animal: "+getType()+"\nFamilia: "+getFamily()+
    42.             "\nHábitat: "+getHabitat();
    43.    }
    44. }
    45.  

    Y tres animales que extienden de Animal:

    Dog.java
    Código: Java
    1. package org.underc0de.factory;
    2.  
    3. public class Dog extends Animal {
    4.  
    5.    public Dog(You are not allowed to view links. Register or Login type, You are not allowed to view links. Register or Login family, You are not allowed to view links. Register or Login habitat) {
    6.       super(type, family, habitat);
    7.    }
    8.  
    9. }

    Shark.java
    Código: Java
    1. package org.underc0de.factory;
    2.  
    3. public class Shark extends Animal {
    4.  
    5.    public Shark(You are not allowed to view links. Register or Login type, You are not allowed to view links. Register or Login family, You are not allowed to view links. Register or Login habitat) {
    6.       super(type, family, habitat);
    7.    }
    8.  
    9.  
    10. }

    Lion.java
    Código: Java
    1. package org.underc0de.factory;
    2.  
    3. public class Lion extends Animal {
    4.  
    5.    public Lion(You are not allowed to view links. Register or Login type, You are not allowed to view links. Register or Login family, You are not allowed to view links. Register or Login habitat) {
    6.       super(type, family, habitat);
    7.    }
    8.  
    9.  
    10. }

    Bien, ya tenemos nuestros 3 tipos de animales que heredan de Animal: Dog, Shark y Lion. Como la tarea es construir objetos sin especificar de qué tipo son, creamos una fábrica abstracta que especifica la creación de un Animal genérico sin especificar de qué tipo:

    AbstractAnimalFactory.java
    Código: Java
    1. package org.underc0de.factory;
    2.  
    3. public interface AbstractAnimalFactory {
    4.  
    5.    Animal createAnimal();
    6. }

    Ahora, el siguiente paso es hacer las implementaciones de ésta fábrica abstracta, es decir las fábricas concretas que crearán los objetos concretos:

    DogFactory.java
    Código: Java
    1. package org.underc0de.factory;
    2.  
    3. public class DogFactory implements AbstractAnimalFactory {
    4.  
    5.    protected You are not allowed to view links. Register or Login type;
    6.    protected You are not allowed to view links. Register or Login family;
    7.    protected You are not allowed to view links. Register or Login habitat;
    8.    
    9.    public DogFactory(You are not allowed to view links. Register or Login type, You are not allowed to view links. Register or Login family, You are not allowed to view links. Register or Login habitat) {
    10.       this.type = type;
    11.       this.family = family;
    12.       this.habitat = habitat;
    13.    }
    14.    
    15.    @Override
    16.    public Animal createAnimal() {
    17.       return new Dog(type, family, habitat);
    18.    }
    19.  
    20. }

    SharkFactory.java
    Código: Java
    1. package org.underc0de.factory;
    2.  
    3. public class SharkFactory implements AbstractAnimalFactory {
    4.  
    5.    protected You are not allowed to view links. Register or Login type;
    6.    protected You are not allowed to view links. Register or Login family;
    7.    protected You are not allowed to view links. Register or Login habitat;
    8.    
    9.    public SharkFactory(You are not allowed to view links. Register or Login type, You are not allowed to view links. Register or Login family, You are not allowed to view links. Register or Login habitat) {
    10.       this.type = type;
    11.       this.family = family;
    12.       this.habitat = habitat;
    13.    }
    14.    
    15.    @Override
    16.    public Animal createAnimal() {
    17.       return new Shark(type, family, habitat);
    18.    }
    19.  
    20. }

    LionFactory.java
    Código: Java
    1. package org.underc0de.factory;
    2.  
    3. public class LionFactory implements AbstractAnimalFactory {
    4.  
    5.    protected You are not allowed to view links. Register or Login type;
    6.    protected You are not allowed to view links. Register or Login family;
    7.    protected You are not allowed to view links. Register or Login habitat;
    8.    
    9.    public LionFactory(You are not allowed to view links. Register or Login type, You are not allowed to view links. Register or Login family, You are not allowed to view links. Register or Login habitat) {
    10.       this.type = type;
    11.       this.family = family;
    12.       this.habitat = habitat;
    13.    }
    14.    
    15.    @Override
    16.    public Animal createAnimal() {
    17.       return new Lion(type, family, habitat);
    18.    }
    19.  
    20. }

    Analicemos un poco el código. Cada una de las implementaciones de AbstractAnimalFactory especifican la implementación que tendrá para crear un tipo de animal.

    Cada factoría concreta, tiene las 3 propiedades que necesita cada objeto para poder crearse. Así mismo, dichos datos se pasan como parámetros a su constructor para establecer los valores en las propiedades que se utilizarán para crear una instancia del objeto.

    Establece las propiedades:

    Código: Java
    1. public LionFactory(You are not allowed to view links. Register or Login type, You are not allowed to view links. Register or Login family, You are not allowed to view links. Register or Login habitat)

    Y usa esas mismas propiedades para crear el objeto:

    Código: Java
    1. @Override
    2. public Animal createAnimal() {
    3.    return new Lion(type, family, habitat);
    4. }

    Finlamente, se sobre-escribe el método de la factoría abstracta createAnimal() para retornar un nuevo objeto de acuerdo al tipo de factoría. Así, la factoría de Perros, creará objetos tipo Perro, la factoría de Tiburones creará objetos tipo Tiburón y la factoría de Leones, crearán objetos tipo León.

    Por último, especificamos una Fábrica global que utilizará las 3 fábricas para crear los objetos (Aquí se aplica también el patrón Facade):

    AnimalFactory.java
    Código: Java
    1. package org.underc0de.factory;
    2.  
    3. public abstract class AnimalFactory {
    4.  
    5.    public static Animal create(AbstractAnimalFactory factory) {
    6.       return factory.createAnimal();
    7.    }
    8. }

    Ésta clase recibe un objeto que implemente la interfaz AbstractAnimalFactory, por lo tanto podrá recibir objetos tipo: DogFactory, SharkFactory y LionFactory. Luego simplemente usa la factoría especificada para crear un animal mediante polimorfismo.

    Ahora construyamos nuestra clase principal para probar el funcionamiento del patrón:

    FactoryTest.java
    Código: Java
    1. package org.underc0de.factory;
    2.  
    3. public class FactoryTest {
    4.  
    5.    public static void main(You are not allowed to view links. Register or Login[] args) {
    6.       Animal dog = AnimalFactory.create(new DogFactory("Perro","Caninos","Doméstico"));
    7.       Animal shark = AnimalFactory.create(new SharkFactory("Tiburón", "Lámnidos", "Mar"));
    8.       Animal lion = AnimalFactory.create(new LionFactory("León", "Felinos", "Selva"));
    9.      
    10.       You are not allowed to view links. Register or Login.out.println(dog.toString());
    11.       You are not allowed to view links. Register or Login.out.println();
    12.       You are not allowed to view links. Register or Login.out.println(shark.toString());
    13.       You are not allowed to view links. Register or Login.out.println();
    14.       You are not allowed to view links. Register or Login.out.println(lion.toString());
    15.    }
    16. }

    Utilizamos el método estático create() de AnimalFactory que recibe una implementación de la interfaz AbstractAnimalFactory, en éste caso un objeto DogFactory al que se le asignan los valores “Perro”, “Caninos” y “Doméstico” y finalmente AnimalFactory llama al método createAnimal() de DogFactory para crear un animal tipo Dog y devolverlo hacia AnimalFactory que lo devuelve y lo guarda en el objeto 'dog'. El mismo procedimiento es para todas las factorías.

    Salida:

    Código: You are not allowed to view links. Register or Login
    Tipo de animal: Perro
    Familia: Caninos
    Hábitat: Doméstico

    Tipo de animal: Tiburón
    Familia: Lámnidos
    Hábitat: Mar

    Tipo de animal: León
    Familia: Felinos
    Hábitat: Selva

    Y de ésta manera sencilla, podemos usar tantas fábricas como queramos para poder crear objetos si generar dependencias ;)


    PATRÓN SINGLETON


    Cuándo usarlo:

  • Cuando la aplicación requiere que solo exista una instancia de un determinado objeto.[/li]

    Problema: Encapsular la configuración de una aplicación en un objeto y compartirlo con los demás objetos de la aplicación que lo requiera.

    Solución: Utilizar el patrón Singleton para encapsular la configuración de la aplicación.

    Para utilizar éste patrón se deben seguir dos reglas:

  • El primer paso es hacer el constructor privado para que no se pueda llamar y por lo tanto, no se puedan crear instancias.[/li]
  • El segundo paso es crear una instancia de la clase y devolverla mediante un método estático.[/li][/list]

    Teniendo en cuenta éstas reglas, creamos una clase que representa a la configuración de la aplicación:

    Configuration.java
    Código: Java
    1. package org.underc0de.singleton;
    2.  
    3. import java.util.HashMap;
    4. import java.util.Map;
    5.  
    6. public class Configuration {
    7.  
    8.    private Map<You are not allowed to view links. Register or Login,Object> appOptions = null;
    9.    private static Configuration config;
    10.    
    11.    private Configuration() {
    12.      
    13.    }
    14.    
    15.    public static Configuration getConfiguration() {
    16.       if(config == null) {
    17.          config = new Configuration();
    18.       }
    19.       return config;
    20.    }
    21.  
    22.    public Map<You are not allowed to view links. Register or Login,Object> getAppOptions() {
    23.       if(appOptions == null) {
    24.          appOptions = new HashMap<>();
    25.          appOptions.put("theme", "dark");
    26.          appOptions.put("show_hidde_files", true);
    27.       }
    28.       return appOptions;
    29.    }
    30.  
    31.    public void setAppOptions(Map<You are not allowed to view links. Register or Login,Object> appOptions) {
    32.       this.appOptions = appOptions;
    33.    }
    34.    
    35. }

    Y simplemente, cuando la necesitemos, obtenemos su única instancia:

    SingletonTest.java
    Código: Java
    1. package org.underc0de.singleton;
    2.  
    3. import java.util.Map;
    4.  
    5. public class SingletonTest {
    6.  
    7.    public static void main(You are not allowed to view links. Register or Login[] args) {
    8.       Configuration cfg = Configuration.getConfiguration();
    9.      
    10.                 // recorre el hashmap para leer las claves y valores
    11.       for(You are not allowed to view links. Register or Login.Entry<You are not allowed to view links. Register or Login, Object> entry: cfg.getAppOptions().entrySet()) {
    12.          You are not allowed to view links. Register or Login.out.println(entry.getKey()+": "+entry.getValue());
    13.       }
    14.  
    15.    }
    16.  
    17. }

    Salida:

    Código: You are not allowed to view links. Register or Login
    show_hidde_files: true
    theme: dark


    NOTA IMPORTANTE:

    Generalmente, cuando se usa éste patrón, se garantiza que solamente existirá una instancia de dicha clase. Pero, si se trata de una aplicación web y se va a integrar una aplicación web con otra, es probable que ya no exista una sola instancia.

    Ésto se debe a los ClassLoaders. Cada contenedor de cada aplicación web (WAR) tiene su propio ClassLoader, por lo que en el supuesto caso de una integración de WARs, las instancias serán dos y no una como se había previsto.

    Una mejor forma de de implementar el patrón Singleton es mediante un enum, como recomienda Joshua Bloch. Al ser un enum, todas sus propiedades serán constantes únicas, no se pueden crear nuevas, solo utilizar las ya descritas.

    Código: Java
    1. public enum Configuration {
    2.    INSTANCE;
    3.    
    4.    private Map<You are not allowed to view links. Register or Login, Object> options;
    5.    
    6.    public Map<You are not allowed to view links. Register or Login, Object> getOptions() {
    7.       if(options == null)
    8.          fillOptions();
    9.       return options;
    10.    }
    11.    
    12.    private void fillOptions() {
    13.       options = new HashMap<>();
    14.       options.put("theme", "Dark");
    15.       options.put("show_hidden_files", true);
    16.    }
    17.    
    18. }


    En el capítulo II, veremos más patrones de diseño. Nos vemos.



    By Gus.
« Última modificación: Abril 26, 2015, 10:36:34 pm por Gus Garsaky »

Conectado ANTRAX

  • *
  • Administrator
  • Mensajes: 5702
  • Actividad:
    100%
  • Country: ar
  • Reputación 37
  • ANTRAX
  • Skype: underc0de.org
  • Twitter: @Underc0de
    • Ver Perfil
    • Underc0de
    • Email

Re:Patrones de diseño

  • en: Abril 26, 2015, 10:11:00 pm
Excelente como siempre bro!
A ver si luego nos dedicas un paper a nosotros que diga:

package underc0de.singleton;

jajajaj

Saludos y muchas gracias!


Desconectado Gus Garsaky

  • *
  • Underc0der
  • Mensajes: 93
  • Actividad:
    0%
  • Reputación -1
  • Skype: gus.garsaky
    • Ver Perfil

Re:Patrones de diseño

  • en: Abril 26, 2015, 10:37:53 pm
Editado. Ahora el namespace es org.underc0de.
« Última modificación: Mayo 03, 2015, 10:29:43 am por #Gustavo »

Desconectado Habraam

  • *
  • Underc0der
  • Mensajes: 4
  • Actividad:
    0%
  • Reputación 0
  • Skype: no
    • Ver Perfil
    • Email

Re:Patrones de diseño

  • en: Abril 27, 2015, 01:07:54 pm
Me encantan este tipo de tutoriales en los que se nos motivan las neuronas con informaciones así de importantes.

Desconectado Gus Garsaky

  • *
  • Underc0der
  • Mensajes: 93
  • Actividad:
    0%
  • Reputación -1
  • Skype: gus.garsaky
    • Ver Perfil

Re:Patrones de diseño

  • en: Abril 27, 2015, 01:11:12 pm
Hola Habraam,

Qué bueno que te haya gustado la publicación. Tienes razón, éstos temas son muy importantes y hay que tenerlos claros. Además, como bien dices, te motiva a hacer un mejor código.
« Última modificación: Mayo 03, 2015, 10:28:49 am por #Gustavo »

Desconectado Expermicid

  • *
  • Ex-Staff
  • *****
  • Mensajes: 461
  • Actividad:
    13.33%
  • Reputación 0
  • _-Expermicid-_
  • Skype: expermicid.xd
    • Ver Perfil

Re:Patrones de diseño

  • en: Abril 27, 2015, 01:12:58 pm
Felicidades por el aporte!!!
Muy buen material y de seguro servirá a muchos.

Saludos

Desconectado Nosferatu

  • *
  • Underc0der
  • Mensajes: 57
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil

Re:Patrones de diseño

  • en: Abril 27, 2015, 05:24:27 pm
Hermano Gus Garsaky.

Muy buen post. Muy bien estructurado. Me gusta.

Saludos Cordiales.

Desconectado Gus Garsaky

  • *
  • Underc0der
  • Mensajes: 93
  • Actividad:
    0%
  • Reputación -1
  • Skype: gus.garsaky
    • Ver Perfil

Re:Patrones de diseño

  • en: Abril 27, 2015, 05:39:04 pm
@Expermicid, @Orlok, muchas gracias por sus comentarios, muchachos.
« Última modificación: Mayo 03, 2015, 10:24:26 am por #Gustavo »

Desconectado marijane88

  • *
  • Underc0der
  • Mensajes: 1
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil

Re:Patrones de diseño

  • en: Julio 25, 2015, 02:18:20 am
Excelente aporte, muy bien explicado.

 

Videos Sobre Patrones de Diseño

Iniciado por Expermicid

Respuestas: 1
Vistas: 4024
Último mensaje Septiembre 24, 2013, 07:21:09 am
por Flemon