miércoles, 13 de abril de 2016

Patrones de Diseño Creacionales Parte 1

1. Abstract Factory: Nos permite crear, mediante una interfaz, conjuntos o familias de objetos (denominados productos) que dependen mutuamente y todo esto sin especificar cual es el objeto concreto. Este patrón se aplica cuando un sistema debe ser independiente de como sus objetos son creados, cuando un sistema deber ser 'configurado' con una cierta familia de productos y se necesita reforzar la noción de dependencia mutua entre ciertos objetos.

Representación UML

Ejemplo

Se Crea una interface Bank(Banco).

  1. import java.io.*;     
  2. interface Bank{  
  3.         String getBankName();  
  4. }  
Se crea  las clases concretas que implementa la interface Bank.

  1. class HDFC implements Bank{  
  2.          private final String BNAME;  
  3.          public HDFC(){  
  4.                 BNAME="HDFC BANK";  
  5.         }  
  6.         public String getBankName() {  
  7.                   return BNAME;  
  8.         }  
  9. }  
  1. class ICICI implements Bank{  
  2.        private final String BNAME;  
  3.        ICICI(){  
  4.                 BNAME="ICICI BANK";  
  5.         }  
  6.         public String getBankName() {  
  7.                   return BNAME;  
  8.        }  
  9. }  
  1. class SBI implements Bank{  
  2.       private final String BNAME;  
  3.       public SBI(){  
  4.                 BNAME="SBI BANK";  
  5.         }  
  6.        public String getBankName(){  
  7.                   return BNAME;  
  8.        }  
  9. }  

Se crea la clase abstracta Loan.

  1. abstract class Loan{  
  2.    protected double rate;  
  3.    abstract void getInterestRate(double rate);  
  4.    public void calculateLoanPayment(double loanamount, int years)  
  5.    {  
  6.         /* 
  7.               to calculate the monthly loan payment i.e. EMI   
  8.                             
  9.               rate=annual interest rate/12*100; 
  10.               n=number of monthly installments;            
  11.               1year=12 months. 
  12.               so, n=years*12; 
  13.  
  14.             */  
  15.                 
  16.          double EMI;  
  17.          int n;  
  18.   
  19.          n=years*12;  
  20.          rate=rate/1200;  
  21.          EMI=((rate*Math.pow((1+rate),n))/((Math.pow((1+rate),n))-1))*loanamount;  
  22.   
  23. System.out.println("your monthly EMI is "+ EMI +" for the amount"+loanamount+
  24.  " you have borrowed");     
  25.  }  
  26. }// end of the Loan abstract class.  

 Se crea las clases concretas que extiende la clase abstracta Loan


  1. class HomeLoan extends Loan{  
  2.      public void getInterestRate(double r){  
  3.          rate=r;  
  4.     }  
  5. }//End of the HomeLoan class.  
  1. class BussinessLoan extends Loan{  
  2.     public void getInterestRate(double r){  
  3.           rate=r;  
  4.      }  
  5.   
  6. }//End of the BusssinessLoan class.  
  1. class EducationLoan extends Loan{  
  2.      public void getInterestRate(double r){  
  3.        rate=r;  
  4.  }  
  5. }//End of the EducationLoan class.  
Se crear una clase abstracta (Ex. AbstractFactory) a obtener los factores para los Objetos Bank y Loan

  1. abstract class AbstractFactory{  
  2.   public abstract Bank getBank(String bank);  
  3.   public abstract Loan getLoan(String loan);  
  4. }  
Crea las clases factores que hereda la clase AbstractFactory a generar el objeto de la clase concreta en la información dada

  1. class BankFactory extends AbstractFactory{  
  2.    public Bank getBank(String bank){  
  3.       if(bank == null){  
  4.          return null;  
  5.       }  
  6.       if(bank.equalsIgnoreCase("HDFC")){  
  7.          return new HDFC();  
  8.       } else if(bank.equalsIgnoreCase("ICICI")){  
  9.          return new ICICI();  
  10.       } else if(bank.equalsIgnoreCase("SBI")){  
  11.          return new SBI();  
  12.       }  
  13.       return null;  
  14.    }  
  15.   public Loan getLoan(String loan) {  
  16.       return null;  
  17.    }  
  18. }//End of the BankFactory class.  
  1. class LoanFactory extends AbstractFactory{  
  2.            public Bank getBank(String bank){  
  3.                 return null;  
  4.           }  
  5.         
  6.      public Loan getLoan(String loan){  
  7.       if(loan == null){  
  8.          return null;  
  9.       }  
  10.       if(loan.equalsIgnoreCase("Home")){  
  11.          return new HomeLoan();  
  12.       } else if(loan.equalsIgnoreCase("Business")){  
  13.          return new BussinessLoan();  
  14.       } else if(loan.equalsIgnoreCase("Education")){  
  15.          return new EducationLoan();  
  16.       }  
  17.       return null;  
  18.    }  
  19.      
  20. }  
Se crea una clase FactoryCreator a obtener los factores para pasar información tal como Bank or Loan.
  1. class FactoryCreator {  
  2.      public static AbstractFactory getFactory(String choice){  
  3.       if(choice.equalsIgnoreCase("Bank")){  
  4.          return new BankFactory();  
  5.       } else if(choice.equalsIgnoreCase("Loan")){  
  6.          return new LoanFactory();  
  7.       }  
  8.       return null;  
  9.    }  
  10. }//End of the FactoryCreator.  

Use el FactoryCreator  a obtener AbstractFactory en orden a ir a los factores de clases concretas para pasar una innformación tal como el tipo.

  1. import java.io.*;  
  2. class AbstractFactoryPatternExample {  
  3.       public static void main(String args[])throws IOException {  
  4.        
  5.       BufferedReader br=new BufferedReader(new InputStreamReader(System.in));  
  6.   
  7.       System.out.print("Enter the name of Bank from where you want to take loan amount: ");  
  8.       String bankName=br.readLine();  
  9.   
  10. System.out.print("\n");  
  11. System.out.print("Enter the type of loan e.g. home loan or business loan or education loan : ");  
  12.   
  13. String loanName=br.readLine();  
  14. AbstractFactory bankFactory = FactoryCreator.getFactory("Bank");  
  15. Bank b=bankFactory.getBank(bankName);  
  16.   
  17. System.out.print("\n");  
  18. System.out.print("Enter the interest rate for "+b.getBankName()+ ": ");  
  19.   
  20. double rate=Double.parseDouble(br.readLine());  
  21. System.out.print("\n");  
  22. System.out.print("Enter the loan amount you want to take: ");  
  23.   
  24. double loanAmount=Double.parseDouble(br.readLine());  
  25. System.out.print("\n");  
  26. System.out.print("Enter the number of years to pay your entire loan amount: ");  
  27. int years=Integer.parseInt(br.readLine());  
  28.   
  29. System.out.print("\n");  
  30. System.out.println("you are taking the loan from "+ b.getBankName());  
  31.   
  32. AbstractFactory loanFactory = FactoryCreator.getFactory("Loan");  
  33.            Loan l=loanFactory.getLoan(loanName);  
  34.            l.getInterestRate(rate);  
  35.            l.calculateLoanPayment(loanAmount,years);  
  36.   }  
  37. }//End of the  AbstractFactoryPatternExample  


2. Builder: Este patrón permite separar la construcción de un objeto complejo de su representación, de modo que el mismo proceso de construcción puede crear diferentes representaciones de este objeto. En términos generales un builder esconde los detalles de la creación de un objeto final que se llama producto. Hay varios métodos para lograr esto, y por ello hay varias "implementaciones" de este patrón que en nada coinciden, salvo en nombre.

Representación UML

Ejemplo

A continuación mostramos  un ejemplo en el que utilizamos este patrón de diseño para construir diferentes tipos de objetos Coche() con un determinado equipamiento de serie cada uno de ellos(básico, medio y full equipo):

  1.    package Builder01;

    public class Main
    {
        public static void main(String[] args)
        {
            // Crear el objeto Director
            Director objFabrica = new Director();

            // Crear los objetos ConcreteBuilder
            BuilderCoche base  = new ConstructorCocheBase();
            BuilderCoche medio = new ConstructorCocheMedio();
            BuilderCoche full  = new ConstructorCocheFull();

            // Construir un coche con equipamiento base
            objFabrica.construir( base );
            Coche cocheBase = base.getCoche();

            // Construir un coche con equipamiento medio
            objFabrica.construir( medio );
            Coche cocheMedio = medio.getCoche();

            // Construir un coche con equipamiento full
            objFabrica.construir( full );
            Coche cocheFull = full.getCoche();

            // Mostrar la información de cada coche creado
            mostrarCaracteristicas( cocheBase );
            mostrarCaracteristicas( cocheMedio );
            mostrarCaracteristicas( cocheFull );
        }

        // --------------------------------

        public static void mostrarCaracteristicas( Coche coche )
        {
            System.out.println( "Motor: " + coche.getMotor() );
            System.out.println( "Carrocería: " + coche.getCarroceria() );
            System.out.println( "Elevalunas eléctrico: " + coche.getElevalunasElec() );
            System.out.println( "Airea acondicionado: " + coche.getAireAcond() );

            System.out.println("===================================");
        }
    }

Director

  1. package Builder01;

    public class Director
    {

        public Director() {
        }

        // --------------------------

        public void construir( BuilderCoche builder )
        {
            builder.crearNuevoCoche();

            builder.construirMotor();
            builder.construirCarroceria();
            builder.construirElevalunas();
            builder.construirAireAcond();
        }
    }


     
     
BuilderCoche.java(un Builder en el diagrama anterior):

  1. package Builder01;

    public abstract class BuilderCoche
    {
        protected Coche coche;

        // ------------------------------

        public Coche getCoche() {
            return this.coche;
        }

        // ------------------------------

        public void crearNuevoCoche() {
            this.coche = new Coche();
        }

        // ------------------------------------

        // Métodos que deberán ser construídos por las clases que hereden de ésta
        public abstract void construirMotor();
        public abstract void construirCarroceria();
        public abstract void construirAireAcond();
        public abstract void construirElevalunas();
    }


     
     

ConstructorCocheBase.java(un ConcreteBuilder  en el diagrama anterior):

  1. package Builder01;

    public class ConstructorCocheBase extends BuilderCoche
    {
        public ConstructorCocheBase() {
        }

        // ------------------------------

        @Override
        public void construirMotor() {
            this.coche.setMotor( "Motor de potencia mínima" );
        }

        // ------------------------------

        @Override
        public void construirCarroceria() {
            this.coche.setCarroceria( "Carrocería de baja protección" );
        }

        // ------------------------------

        @Override
        public void construirAireAcond() {
            this.coche.setAireAcond( false );
        }

        // ------------------------------

        @Override
        public void construirElevalunas() {
            this.coche.setElevalunasElec( false );
        }
    }

ConstructorCocheMedio.java (un ConcreteBuilder en el diagrama anterior):

  1. package Builder01;

    public class ConstructorCocheMedio extends BuilderCoche
    {
        public ConstructorCocheMedio() {
        }

        // ------------------------------

        @Override
        public void construirMotor() {
            this.coche.setMotor( "Motor de potencia media" );
        }

        // ------------------------------

        @Override
        public void construirCarroceria() {
            this.coche.setCarroceria( "Carrocería de protección media" );
        }

        // ------------------------------

        @Override
        public void construirAireAcond() {
            this.coche.setAireAcond( false );
        }

        // ------------------------------

        @Override
        public void construirElevalunas() {
            this.coche.setElevalunasElec( true );
        }
    }


 ConstructorCocheFull.java (un ConcreteBuilder en el diagrama anterior):

  1. package Builder01;

    public class ConstructorCocheFull extends BuilderCoche
    {
        public ConstructorCocheFull() {
        }

        // ------------------------------

        @Override
        public void construirMotor() {
            this.coche.setMotor( "Motor de potencia alta" );
        }

        // ------------------------------

        @Override
        public void construirCarroceria() {
            this.coche.setCarroceria( "Carrocería de alta protección" );
        }

        // ------------------------------

        @Override
        public void construirAireAcond() {
            this.coche.setAireAcond( true );
        }

        // ------------------------------

        @Override
        public void construirElevalunas() {
            this.coche.setElevalunasElec( true);
        }
    }

Coche.java (un Product en el diagrama anterior):

  1. package Builder01;

    public class Coche
    {
        private String motor = "";
        private String carroceria = "";
        private Boolean elevalunasElec = false;
        private Boolean aireAcond = false;

        // -------------------------------------------

        public Coche() {
        }

        // -------------------------------------------

        public String getMotor() {
            return this.motor;
        }

        // -------------------------------------------

        public void setMotor(String motor) {
            this.motor = motor;
        }

        // -------------------------------------------

        public String getCarroceria() {
            return this.carroceria;
        }

        // -------------------------------------------

        public void setCarroceria(String carroceria) {
            this.carroceria = carroceria;
        }

        // -------------------------------------------

        public Boolean getElevalunasElec() {
            return elevalunasElec;
        }

        // -------------------------------------------

        public void setElevalunasElec(Boolean elevalunasElec) {
            this.elevalunasElec = elevalunasElec;
        }

        // -------------------------------------------

        public Boolean getAireAcond() {
            return aireAcond;
        }

        // -------------------------------------------

        public void setAireAcond(Boolean aireAcond) {
            this.aireAcond = aireAcond;
        }
    }

 En el programa principal creamos el objeto de tipo Director, así como los de tipo ConcreteBuilder que le iremos pasando a continuación como parámetro a través de su método construir() ( con el fin de crear objetos Coche equipados de diferentes formas). Observa que en dicho método se llama a su vez a los diferentes métodos de la clase BuilderCoche, mediante los que se crea un nuevo objeto de tipo Coche y  se componen las diferentes partes del mismo. Posteriormente se realiza una llamada al método getCoche() del objeto de tipo Director para obtener cada objeto de tipo Coche, y se muestran sus características.











No hay comentarios:

Publicar un comentario