patron_II

Patrones de diseño en Android (II): Patrones estructurales

Patrones de diseño en Android (I) : Patrones de creación
Patrones de diseño en Android (II): Patrones estructurales

Siguiendo la línea de patrones de diseño que comenzamos con los patrones de creación, seguimos con los patrones estructurales más utilizados en el desarrollo mobile. Éstos son: Adapter, Facade, y Proxy.

Adapter

El patrón adaptador consiste en crear una clase intermedia para poder ajustar el resultado a una salida esperada. Pongamos un pequeño ejemplo. Imaginaos que tenemos una interfaz(“Phone”) que define los métodos que deben implementar todos los teléfonos.

/**
 * Interface that defines the methods for every phone.
 *
 * @author asanchezyu@gmail.com.
 * @version 1.0.
 * @since 25/4/16.
 */
public interface Phone {

    /**
     * Dialing numbers.
     */
    void dialNumbers();

    /**
     * Make a phone call.
     */
    void makeCall();

}

En 1980 existían solo teléfonos fijos “LandlinePhone”, los cuales implementaban estos métodos sin problema.

/**
 * LandlinePhone entity.
 *
 * @author asanchezyu@gmail.com.
 * @version 1.0.
 * @since 25/4/16.
 */
public class LandlinePhone implements Phone{

    @Override
    public void dialNumbers() {
        System.out.println("Dialing numbers from landline phone");
    }

    @Override
    public void makeCall() {
        System.out.println("Making phone call from landline phone");
    }
}

A principios del año 2000 aparecen los teléfonos móviles los cuales tienen otros métodos diferentes a los definidos en la interfaz.

/**
 * Smartphone entity.
 *
 * @author asanchezyu@gmail.com.
 * @version 1.0.
 * @since 25/4/16.
 */
public class SmartPhone {

    public void touchScreenForNumbers(){
        System.out.println("Dialing numbers from smartphone");
    }

    public void makePhoneCall(){
        System.out.println("Making phone call from smartphone");
    }

}

Podremos crear una clase “Wrapper” , la cual adaptará los métodos nuevos a los antiguos.

/**
 * Wrapper from {@link SmartPhone} to {@link Phone}.
 *
 * @author asanchezyu@gmail.com.
 * @version 1.0.
 * @since 25/4/16.
 */
public class SmartphoneWrapper implements Phone{

    private SmartPhone smartPhone = new SmartPhone();

    @Override
    public void dialNumbers() {
        smartPhone.touchScreenForNumbers();
    }

    @Override
    public void makeCall() {
        smartPhone.makePhoneCall();
    }
}

 


Facade

El patrón “Facade” o “Fachada” tiene como objetivo hacer que la comunicación entre dos elementos sea mas sencilla gracias al uso de interfaces, haciendo invisible ciertas partes que pudieran ser más complejas. Pongamos un ejemplo:
Tenemos un sistema en el cual se pueden dar de alta usuarios con su nombre junto con su password. Pero hay ciertos campos que al que va a hacer el registro no le interesan (fecha del registro, sistema,etc..), por lo que al crear una fachada para este proceso, facilitaremos el proceso.

/**
 * User entity.
 *
 * @author asanchezyu@gmail.com.
 * @version 1.0.
 * @since 25/4/16.
 */
public class User {

    private String username;

    private String password;

    private String system;

    private Date registrationDate;

    public User() {
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Date getRegistrationDate() {
        return registrationDate;
    }

    public void setRegistrationDate(Date registrationDate) {
        this.registrationDate = registrationDate;
    }

    public String getSystem() {
        return system;
    }

    public void setSystem(String system) {
        this.system = system;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}
/**
 * Facade for registration process.
 *
 * @author asanchezyu@gmail.com.
 * @version 1.0.
 * @since 25/4/16.
 */
public class RegisterFacade {

    private RegistrationManager registrationManager;

    public RegisterFacade() {

        registrationManager = new RegistrationManager();

    }

    public void registerUser(String username, String password){

        User user = new User();

        user.setUsername( username );

        user.setPassword( password );

        user.setRegistrationDate( new Date() );

        user.setSystem("MacOS X - 10.10.5");

        registrationManager.makeRegistry( user );

    }

}
/**
 * Registration manager.
 *
 * @author asanchezyu@gmail.com.
 * @version 1.0.
 * @since 25/4/16.
 */
public class RegistrationManager {

    public void makeRegistry(User user) {

        SimpleDateFormat sdf = new SimpleDateFormat("dd/mm/yyyy");

        System.out.println(
                "We'll made the registration for user with data: "
                + "\n\tUsername:\t" + user.getUsername()
                + "\n\tPassword:\t" + user.getPassword()
                + "\n\tSystem:\t" + user.getSystem()
                +" \n\tRegistration date:\t" + sdf.format(user.getRegistrationDate())
        );

        // We will make the registration in our system here.Database, rest services,etc...

    }

}

 


Proxy

En informática, el término “proxy” se utiliza en multitud de ocasiones. Este patrón se define como “Proporcionar un representante o sustituto de otro objeto para controlar el acceso a éste con el objetivo de retrasar o controlar y retrasar el coste de inicialización de objetos”.

  • proxy remoto
  • proxy virtual
  • proxy de protección

Pongamos un ejemplo: Tenemos que realizar scrapping de una web. El proceso de conexión y obtención del código de esa web puede ser un proceso muy pesado, por lo que nos interesa poder guardar la referencia de esos datos ya guardados.

Tenemos una interfaz WebParser que define el método de acceso al código de la web.

/**
 * WebParser interface.
 *
 * @author asanchezyu@gmail.com.
 * @version 1.0.
 * @since 9/5/16.
 */
public interface WebParser {
    String getHtmlContent();
}

Por otra parte, tenemos una clase HtmlWebParser que implementa WebParser, la cual realiza las operaciones necesarias para obtener los datos de la página web que necesitemos

/**
 * HtmlWebParser class.
 *
 * @author asanchezyu@gmail.com.
 * @version 1.0.
 * @since 9/5/16.
 */
public class HtmlWebParser implements WebParser {

    private String content;

    private String websiteUrl;

    public HtmlWebParser(String url) {

        websiteUrl = url;

        //Here, we would make the connection to the website, making all the heavy transactions here.

        content = "
Website html content
";

    }

    @Override
    public String getHtmlContent() {

        return content;

    }
}

Por último, tendremos una clase HtmlWebParserProxy también implementa la misma interfaz, pero guarda una instancia de un objeto HtmlWebParser para así evitarnos crear más objetos.

/**
 * Proxy class for html web parser.
 *
 * @author asanchezyu@gmail.com.
 * @version 1.0.
 * @since 9/5/16.
 */
public class HtmlWebParserProxy implements WebParser {

    private HtmlWebParser connection;

    private String websiteUrl;

    public HtmlWebParserProxy(String url) {

        this.websiteUrl = url;

    }

    @Override
    public String getHtmlContent() {

        if (connection == null) {

            System.out.println("New instance of HtmlWebParser");

            connection = new HtmlWebParser(websiteUrl);

        }

        return connection.getHtmlContent();

    }
}

Una vez hecho esto, podremos utilizar nuestra clase proxy de la siguiente manera.

WebParser connection = new HtmlWebParserProxy("http://blog.asanchez-portfolio.es");
System.out.println(connection.getHtmlContent());
System.out.println(connection.getHtmlContent());

En la salida por consola podremos observar que solo se crea una instancia con lo que el código solo se descargará una vez :

...
New instance of HtmlWebParser

Website html content

Website html content
...

 Puedes ver el código completo en GITHUB


Deja un comentario

6 + 12 =