Author Archives: admin

Los amateurs se enfadan con los clientes, los profesionales los educan

[fuente: http://99u.com/articles/18303/we-deserve-the-clients-we-get]

Como la mayoría de los freelancers con experiencia saben, algunas veces tenemos que dejar de trabajar con clientes por nuestro beneficio y el suyo. Pero no tiene porqué suceder de esta manera.

Yo solía pensar que tratar con clientes frustrados era solo un asunto de tener mano izquierda. Pero entonces me di cuenta , que si bien es verdad que en todas las relaciones hay aspectos frustrantes, la frustración debería ser la excepción de la regla.

Hay momentos puntuales en el camino a convertirnos en la versión freelance de Donald Trump , en el que gritamos “‘¡No quiero trabajar contigo!” a cualquiera que esté en desacuerdo contigo. Aunque lo cierto es , que merecemos los clientes que tenemos. Los malos clientes no son el resultado de alguna fuerza cósmica que está en nuestra contra , sino que más bien son el resultado de nuestras propias acciones.

Los clientes frunstrantes son el resultado de algún paso en falso que hemos dado a lo largo del camino. Para hacer lo mejor que opdamos nuestro trabajo con la mejor gente posible, necesitamos ser diligentes (cuidadosos) en nuestras relaciones con nuestros clientes. Aquí os muestro como:

Tener los cojones de decir “no”

Si no es un buen proyecto para tí, alejate antes de que el dinero se meta por medio. ¿Es el tipo de proyecto por el que quieres ser conocido? Si estas llenando tu curriculum con trabajos en los que no estás interesado, todo lo que estás haciendo es atrayendo más de lo mismo (te recomiendo esta charla : Jason Santa Maria gave a great Creative Mornings talk , trata sobre el poder y el valor de decir no a trabajos). Puede costarte hacerlo , pero piensa que sólo es un cliente.

Huye antes de que haya dinero de por medio.

Deja suficientemente claro tus principios a todos

La forma más fácil de hacer esto es bloguear regularmente en el mismo website donde esté tu portfolio. Escribe honestamente sobre el  trabajo que haces. Eso muestra inmediatamente a los potenciales clientes si sus objetivos y sus valores se corresponden con los tuyos y asi ahorra tiempo si se da que tanto tú como tu cliente estan fuera de sincronía.

Educa a tus clientes

Oportunidades hay. Todos hemos formado parte de muchos proyectos en los que trabajamos cerca o con los propios clientes que nos contratan. Tenemos una gran oportunidad de enseñar a nuestros clientes lo que hemos aprendido de toda nuestra experiencia.

Si un cliente no está de acuerdo con algo que tu sabes que es lo correcto , no te desgastes intentando convencerlo. En su lugar, pon el modo “research”  o investigación. Muestrales algunos ejemplos de porqué lo que ellos quieren no funciona en el proyecto que tenéis entre manos. Y puede pasar que el cliente aún así te haga ver su punto de vista de modo que te convenza que su idea funcionará, en ese caso puedes ceder (y aprender algo en el proceso). Si ellos no consiguen convencerte acabas de apuntarte un tanto mientras les has educado para que vengan más futuros proyectos. Consideralo una inversión en un recurso que necesitas para que tu carrera profesional sea más exitosa.

Interroga a tus potenciales clientes

¿Cuáles son sus preferencias en diseño? ¿Se corresponde eso con el tipo de trabajos en los que estás interesado? No tiene sentido trabajar con un cliente que le gustan las campanas brillantes y los silbiditos si a ti te gustan hacer diseños minimalistas. Filtrar a los clientes te permite elegir los mejores para trabajar y te proporcionan el tipo de trabajo que tu te sientes más cómodo en los que das lo mejor de ti mismo.

Ser claro con los objetivos del proyecto

De esa forma no hay malentendidos, no es una asunto de lo que ellos quieren contra lo que tu quieres, lo cual es altamente subjetivo, es más un asunto de lo que cumple los objetivos del proyecto de la mejor manera. Pon estos objetivos escritos y tenlos como documento de referencia cuando sea necesario.

***

Es duro decir no a los clientes (y al dinero que te pueden hacer ganar), especialmente cuando estás empezando. Pero como otros tipos de emprendimientos creativos, enfocate en la calidad desde el principio y tu carrera será exponencialmente más fácil. Después de todo, los buenos clientes nos traen buenos trabajos , lo que nos hace más felices y realizados  (y menos quejosos a nuestra gente cercana sobre como nuestros clientes no dejan de tomar malas decisiones). Crear un cuerpo de trabajo con el que estés feliz puede llevarte toda una vida.

Nosotros somos los responsables del trabajo que ofrecemos al mundo, asi que por qué no hacemos ese trabajo bien hecho?

PAUL JARVIS

Paul is a Gentleman of Adventure. He’s also a web designer andauthor. If he’s not in nature on some Thoreau-esque tangent (but with wifi), you can find him on twitter at @pjrvs.

GAE: Tareas programadas con cron para Java

El servicio cron de App Engine te permite configurar tareas programadas regularmente que operan en momentos definidos o intervalos regulares. Estas tareas se conocen comúnmente como tareas cron. El servicio cron de App Engine activa automáticamente estas tareas cron. Por ejemplo, puedes utilizarlo para enviar un correo electrónico de informe a diario, para actualizar los datos almacenados en la caché cada 10 minutos o para actualizar la información de resumen cada hora.

Una tarea cron invocará una URL, mediante una solicitud GET HTTP, en un momento concreto del día. Una URL invocada por el servicio cron está sujeta a los mismos límites y cuotas que una solicitud HTTP normal, incluido el límite de tiempo de la solicitud. Las tareas cron se ejecutan únicamente para la versión predeterminada de tu aplicación.

Una aplicación puede contener hasta 20 tareas programadas.

Acerca de cron.xml

Un archivo cron.xml del directorio WEB-INF de la aplicación (junto con appengine-web.xml) controla el servicio cron de la aplicación Java. A continuación, se muestra un ejemplo del archivo cron.xml:

<?xml version="1.0" encoding="UTF-8"?>
<cronentries>
  <cron>
    <url>/recache</url>
    <description>Repopulate the cache every 2 minutes</description>
    <schedule>every 2 minutes</schedule>
  </cron>
  <cron>
    <url>/weeklyreport</url>
    <description>Mail out a weekly report</description>
    <schedule>every monday 08:30</schedule>
    <timezone>America/New_York</timezone>
  </cron>
</cronentries>

En el caso de que un XSD describa el formato, consulta el archivo docs/cron.xsd del SDK.

Un archivo cron.xml consta de varias definiciones de tarea. Una definición de tarea debe contener <url> y <schedule>. Opcionalmente, puedes especificar también<description> y <timezone>. La descripción se puede ver en la consola de administración.

El campo url es simplemente una URL de la aplicación. El formato del campo schedule se trata más detenidamente en la sección Formato de la programación.

La zona horaria debe tener el nombre de una zona horaria zoneinfo estándar. Si no especificas una zona horaria, las tareas se ejecutarán en la hora UTC (también conocida como hora GMT).

Formato de la programación

Las programaciones cron se especifican mediante un formato tipo inglés sencillo.

A continuación, se muestran ejemplos de programaciones:

every 5 minutes
every 12 hours
2nd,third mon,wed,thu of march 17:00
every monday 09:00
1st monday of sep,oct,nov 17:00
every day 00:00

Si no necesitas ejecutar una tarea repetida en un momento específico pero, necesitas ejecutarla en intervalos regulares, utiliza el siguiente formato: every N (hours|mins|minutes), donde N es un número y horas o minutos especifica la unidad de tiempo. El tiempo más breve que se puede especificar en la ejecución de una tarea es 1 minuto.

De forma predeterminada, una programación con intervalos comienza en el siguiente intervalo después de haberse completado la última tarea. Si quieres que las tareas comiencen en intervalos regulares durante el día independientemente del momento en que se completó la última tarea, añade la palabra synchronized a la descripción del intervalo. Por ejemplo:

every 2 hours synchronized

Esta configuración ejecuta una tarea 12 veces al día en intervalos de dos horas, a partir de la medianoche.

Si quieres establecer tiempos más específicos, puedes especificar la programación del siguiente modo:

("every"|ordinal) (days) ["of" (monthspec)] (time)

Los paréntesis se emplean solo a modo de ejemplo y las comillas indican un valor literal.

Donde:

  • ordinal indica una lista separada por comas de “1st”, “first” y así sucesivamente (ambas formas son correctas).
  • days indica una lista de días de la semana separados por comas (por ejemplo, “mon”, “tuesday”; se aceptan tanto la forma corta como la forma larga); “every day” equivale a “every mon,tue,wed,thu,fri,sat,sun”.
  • monthspec indica una lista de meses separados por comas (por ejemplo, “jan”, “march”, “sep”). Si se omite, implica todos los meses. También puedes incluir “month” para indicar todos los meses, como en “1,8,15,22 of month 09:00”.
  • time indica la hora del día, en formato HH:MM y horario de 24 horas.

Protección de direcciones URL para cron

Para evitar que los usuarios accedan a las URL utilizadas por las tareas programadas, puedes restringir el acceso a las cuentas del administrador. Las tareas programadas pueden acceder a las URL exclusivas de los administradores. Puedes obtener más información sobre cómo restringir las URL en la sección Seguridad y autenticación. A continuación, se muestra un ejemplo que puedes utilizar en web.xml para restringir todo lo que empiece por /cron/ únicamente a los administradores:

    <security-constraint>
        <web-resource-collection>
            <url-pattern>/cron/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>

Nota: aunque las tareas cron pueden utilizar rutas de URL restringidas con <role-name>admin</role-name>no pueden utilizar rutas de URL restringidas con <role-name>*</role-name>.

Para obtener más información sobre el formato de web.xml, consulta la documentación del descriptor de implementación.

Para probar una tarea cron, accede como administrador e introduce la URL del controlador en el navegador.

Las solicitudes procedentes del servicio cron contienen también una cabecera HTTP:

X-AppEngine-Cron: true

Si te quieres asegurar de que solo las solicitudes cron puedan activar el controlador, busca esta cabecera.

Versiones de cron y de la aplicación

Las solicitudes cron siempre se envían a la versión predeterminada de la aplicación.

Subida de tareas cron

Puedes utilizar AppCfg para subir las tareas cron. Cuando subas la aplicación a App Engine a través de AppCfg update, el servicio cron se actualizará con el contenido decron.xml. Puedes actualizar solo la configuración cron sin subir el resto de la aplicación a través de AppCfg update_cron.

Para eliminar todas las tareas cron, modifica el archivo cron.xml para que contenga solo lo siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<cronentries/>

Compatibilidad del servicio cron con la Consola del administrador

La Consola del administrador te permite ver el estado de tus tareas cron. Selecciona el enlace “Tareas cron” en el menú lateral para ver el estado de las tareas, incluida la última vez que se ejecutó la tarea, así como su resultado.

Para ver cuándo se han añadido o eliminado las tareas cron, selecciona la página Registros del administrador en el menú de la Consola del administrador.

Compatibilidad del servicio cron con el servidor de desarrollo

El servidor de desarrollo no ejecuta automáticamente las tareas cron. Puedes utilizar el servicio cron del escritorio local o la interfaz de tareas programadas para acceder a las URL de las tareas a través de curl o de una herramienta similar.

Prototype Pattern in Java

[Fuente: http://www.journaldev.com/1440/prototype-pattern-in-java]

Prototype pattern is one of the Creational Design pattern, so it provides a mechanism of object creation. Prototype pattern is used when the Object creation is a costly affair and requires a lot of time and resources and you have a similar object already existing. So this pattern provides a mechanism to copy the original object to a new object and then modify it according to our needs. This pattern uses java cloning to copy the object.

It would be easy to understand this pattern with an example, suppose we have an Object that loads data from database. Now we need to modify this data in our program multiple times, so its not a good idea to create the Object using new keyword and load all the data again from database. So the better approach is to clone the existing object into a new object and then do the data manipulation.

Prototype design pattern mandates that the Object which you are copying should provide the copying feature. It should not be done by any other class. However whether to use shallow or deep copy of the Object properties depends on the requirements and its a design decision.

Here is a sample program showing implementation of Prototype pattern.

Employees.java
 
package com.journaldev.design.prototype;
 
import java.util.ArrayList;
import java.util.List;
 
public class Employees implements Cloneable{
 
    private List<String> empList;
     
    public Employees(){
        empList = new ArrayList<String>();
    }
     
    public Employees(List<String> list){
        this.empList=list;
    }
    public void loadData(){
        //read all employees from database and put into the list
        empList.add("Pankaj");
        empList.add("Raj");
        empList.add("David");
        empList.add("Lisa");
    }
     
    public List<String> getEmpList() {
        return empList;
    }
 
    @Override
    public Object clone() throws CloneNotSupportedException{
            List<String> temp = new ArrayList<String>();
            for(String s : this.getEmpList()){
                temp.add(s);
            }
            return new Employees(temp);
    }
     
}

Notice that the clone method is overridden to provide a deep copy of the employees list.

Here is the test program that will show the benefit of prototype pattern usage.
PrototypePatternTest.java
package com.journaldev.design.test;
 
import java.util.List;
 
import com.journaldev.design.prototype.Employees;
 
public class PrototypePatternTest {
 
    public static void main(String[] args) throws CloneNotSupportedException {
        Employees emps = new Employees();
        emps.loadData();
         
        //Use the clone method to get the Employee object
        Employees empsNew = (Employees) emps.clone();
        Employees empsNew1 = (Employees) emps.clone();
        List<String> list = empsNew.getEmpList();
        list.add("John");
        List<String> list1 = empsNew1.getEmpList();
        list1.remove("Pankaj");
         
        System.out.println("emps List: "+emps.getEmpList());
        System.out.println("empsNew List: "+list);
        System.out.println("empsNew1 List: "+list1);
    }
 
}-

Output of the above program is:

1
2
3
emps HashMap: [Pankaj, Raj, David, Lisa]
empsNew HashMap: [Pankaj, Raj, David, Lisa, John]
empsNew1 HashMap: [Raj, David, Lisa]

If the object cloning was not provided, every time we need to make database call to fetch the employee list and then do the manipulations that would have been resource and time consuming.

Builder Design Pattern in Java

[Fuente: http://www.journaldev.com/1425/builder-design-pattern-in-java]

Builder design pattern is a creational design pattern like Factory Pattern and Abstract Factory Pattern. This pattern was introduced to solve some of the problems with Factory and Abstract Factory design patterns when the Object contains a lot of attributes.

There are three major issues with Factory and Abstract Factory design patterns when the Object contains a lot of attributes.

  1. Too Many arguments to pass from client program to the Factory class that can be error prone because most of the time, the type of arguments are same and from client side its hard to maintain the order of the argument.
  2. Some of the parameters might be optional but in Factory pattern, we are forced to send all the parameters and optional parameters need to send as NULL.
  3. If the object is heavy and its creation is complex, then all that complexity will be part of Factory classes that is confusing.

We can solve the issues with large number of parameters by providing a constructor with required parameters and then different setter methods to set the optional parameters but the problem with this is that the Object state will be inconsistent until unless all the attributes are set explicitly.

Builder pattern solves the issue with large number of optional parameters and inconsistent state by providing a way to build the object step-by-step and provide a method that will actually return the final Object.

Builder Pattern Implementation

  1. First of all you need to create a static nested class and then copy all the arguments from the outer class to the Builder class. We should follow the naming convention and if the class name is Computer then builder class should be named as ComputerBuilder.
  2. The Builder class should have a public constructor with all the required attributes as parameters.
  3. Builder class should have methods to set the optional parameters and it should return the same Builder object after setting the optional attribute.
  4. The final step is to provide a build() method in the builder class that will return the Object needed by client program. For this we need to have a private constructor in the Class with Builder class as argument.

Here is the sample code where we have a Computer class and ComputerBuilder class to build it.

 
package com.journaldev.design.builder;
 
public class Computer {
     
    //required parameters
    private String HDD;
    private String RAM;
     
    //optional parameters
    private boolean isGraphicsCardEnabled;
    private boolean isBluetoothEnabled;
     
 
    public String getHDD() {
        return HDD;
    }
 
    public String getRAM() {
        return RAM;
    }
 
    public boolean isGraphicsCardEnabled() {
        return isGraphicsCardEnabled;
    }
 
    public boolean isBluetoothEnabled() {
        return isBluetoothEnabled;
    }
     
    private Computer(ComputerBuilder builder) {
        this.HDD=builder.HDD;
        this.RAM=builder.RAM;
        this.isGraphicsCardEnabled=builder.isGraphicsCardEnabled;
        this.isBluetoothEnabled=builder.isBluetoothEnabled;
    }
     
    //Builder Class
    public static class ComputerBuilder{
 
        // required parameters
        private String HDD;
        private String RAM;
 
        // optional parameters
        private boolean isGraphicsCardEnabled;
        private boolean isBluetoothEnabled;
         
        public ComputerBuilder(String hdd, String ram){
            this.HDD=hdd;
            this.RAM=ram;
        }
 
        public ComputerBuilder setGraphicsCardEnabled(boolean isGraphicsCardEnabled) {
            this.isGraphicsCardEnabled = isGraphicsCardEnabled;
            return this;
        }
 
        public ComputerBuilder setBluetoothEnabled(boolean isBluetoothEnabled) {
            this.isBluetoothEnabled = isBluetoothEnabled;
            return this;
        }
         
        public Computer build(){
            return new Computer(this);
        }
 
    }
 
}

Notice that Computer class has only getter methods and no public constructor, so the only way to get a Computer object is through the ComputerBuilder class.

Here is a test program showing how to use Builder class to get the object.

package com.journaldev.design.test;
 
import com.journaldev.design.builder.Computer;
 
public class TestBuilderPattern {
 
    public static void main(String[] args) {
        //Using builder to get the object in a single line of code and
                //without any inconsistent state or arguments management issues     
        Computer comp = new Computer.ComputerBuilder(
                "500 GB", "2 GB").setBluetoothEnabled(true)
                .setGraphicsCardEnabled(true).build();
    }
 
}

Builder Design Pattern Example in JDK

  • java.lang.StringBuilder#append() (unsynchronized)
  • java.lang.StringBuffer#append() (synchronized)

Los 7 errores que debes evitar al buscar trabajo en Internet

[Fuente: http://www.trabajandoatope.es/los-7-errores-que-debes-evitar-al-buscar-trabajo-en-internet/?goback=%2Egde_3730479_member_5810665777761644544#%21]

 

PERFIL INCOMPLETO

Cuando uno se dispone a buscar trabajo en Internet es muy importante abrirse una cuenta en los portales de empleo donde puedes encontrar trabajo relacionado con tu formación y experiencia. Como consejo, intenta ir más allá de los típicos portales como Infojobs o Infoempleo a donde va todo el mundo. Además estos portales de empleo resultan demasiado generales por lo que encontrarás menos ofertas específicas de tu sector. Investiga cuáles son aquellas webs que cuentan con un número de ofertas de trabajo mayor en tu campo.

Una vez lo hayas hecho, rellena bien tu perfil. Tómate tiempo pues esta es la parte más importante, ya que un curriculum incompleto, además de no dar toda la información necesaria sobre tu perfil dará una imagen de dejadez que no te beneficia en nada. Por eso hasta que no lo hayas hecho no te inscribas para ningún puesto ofertado, pues estarás perdiendo una oportunidad.

 

NO TE CONVIERTAS EN MISTER ELÁSTICO

Como ya he dicho en otras ocasiones, si cometemos errores en nuestro curriculum o en nuestra manera de postular es muy posible que no nos llamen para la entrevista de trabajo y lo más probable es que acabemos frustrados y echando nuestro curriculum a todo lo que se mueva. Es lo que llamamos ser Mister Elástico. Sin duda uno de los mayores errores en los que puedes caer. Y es que la facilidad de poder hacerlo con un sólo click resulta muy tentador en algunos casos, incluso aun sabiendo que no cumplimos con los requisitos. Pensamos tontamente “a ver si suena la flauta”. Sin embargo, ¿realmente crees que con la cantidad de parados que hay actualmente va a sonar la flauta? Si no cumples los requisitos, tranquilo, siempre habrá alguien que sí los cumpla.

business graphics 1428642  Los 7 errores que debes evitar al buscar trabajo en Internet

Por eso es importante que valores tu perfil y que si no cumples con al menos el 95% de los requisitos exigidos, ni te molestes en enviar tu curriculum pues estarás perdiendo un tiempo precioso que podrías estar dedicando a personalizarlo para conseguir mejores resultado al buscar trabajo en Internet. Sin duda, esto te dará más resultados que postular a mil trabajos para los que no tienes ni formación ni experiencia.

 

NO CUIDAR TU IMAGEN EN LA RED

Seguro que cuando te interesa mucho una oferta de trabajo intentas conocer más información acerca de la empresa. Pues esto mismo ocurre cuando una empresa se interesa por tu perfil. Y es que es la forma más sencilla y rápida de conocerte un poco más y poder valorar si eres el candidato idóneo para el puesto y por tanto mereces demostrarlo en la entrevista de trabajo es poniendo tu nombre en Internet. Si eres miembro de alguna o varias redes sociales, es evidente que aparecerá tu perfil entre los resultados de Google.

Por eso no está de más que lo hagas tú mismo y revises si hay datos que puedan comprometerte o boicotear tu candidatura a la hora de buscar trabajo en Internet. Si te interesa el tema puedes leer algunos posts relacionados en la sección “Trabajo y redes sociales”.

 

PASIVIDAD

Si te limitas a echar curriculum solamente en las ofertas de trabajo que ves en los portales de empleo de Internet, estarás perdiéndote muchas oportunidades. Puedes darte cuenta de ello si lees “Ofertas de trabajo VS Candidatura espontánea”. Pero además de buscar trabajo en Internet es importante que no estés parado, sino que realices algún tipo de formación relacionada con tu campo para aumentar tu curriculum. pero también es una buena idea hacer algún cursos sobre aquellas disciplinas más demandadas ahora en el mercado como por ejemplo los idiomas. De esta forma podrás justificar mucho mejor tu inactividad si finalmente estás mucho tiempo en el paro (leer post).

 

NO CUIDAR LOS CONTACTOS EN LAS REDES SOCIALES

Existen muchas redes sociales enfocadas sobre todo a buscar trabajo en Internet por lo que cuentan con un fin claramente profesional. Puedes conocer algunas  de ellas en “Las 6 mejores redes sociales para encontrar trabajo”. Por eso es recomendable que sepas distinguir entre tu entorno personal y profesional. Y es que los departamentos de RR.HH. pueden contactarse entre ellos para conseguir información sobre los candidatos a una oferta de trabajo.

Pero además es importante que cuides tu red de contactos para que pueda servirte de ayuda en tu búsqueda de empleo. Eso sí, como ya he dicho otras veces las redes sociales son una carrera de fondo y no puedes esperar tener un montón de contactos que den la cara por ti para recomendarte en un empleo, si apareces y desapareces a intervalos según tienes empleo o no. Este es uno de los mayores errores, pues es algo que debes cultivar a diario.

90 Los 7 errores que debes evitar al buscar trabajo en Internet

 

DEJAR PASAR LAS NUEVAS OPORTUNIDADES DEL CV ONLINE

Aunque tradicionalmente siempre se ha dicho que lo máximo que debías ocupar eran 2 hojas en tu curriculum, en la actualidad Internet ha cambiado mucho las cosas. La facilidad con la que puede verse un perfil en unos pocos segundos bajando el cursor y el no ocupar nada de espacio en papel hacen que sea posible poder escribir al detalle nuestra formación y nuestra experiencia laboral. De esta forma podremos dar una imagen más acertada de quiénes somos. Por eso debemos aprovechar esta oportunidad al máximo para decir todo lo que queramos y que pensemos que pueda resultar de valor para el puesto de trabajo.

 

DESCARTAR LA VÍA OFFLINE

No obstante aunque centres tu búsqueda en la red, no caigas en uno de loserrores que más cometen las personas al buscar trabajo en Internetque es el de menospreciar la búsqueda de empleo tradicional. Y es que todos los caminos son útiles. No te dejes llevar por la comodidad. De hecho si quieres conseguir tu objetivo, debes agotar todas las vías hasta encontrar trabajo. Por eso si te interesa mucho una oferta de trabajo, no dudes en presentarte en persona en al empresa, ya que si en ese momento tienen un hueco es probable que quieran hacerte una entrevista, algo que no habría ocurrido si te hubieras quedado en casa.

Pero además es importante que todo tu entorno, es decir, tus amigos y familiares se enteren de que estás buscando empleo para que puedan echarte una mano en el caso de que se enteren de alguna oferta de trabajo que encaje con tu perfil.

 

Y aunque no podemos asegurarte que evitar cometer estos errores al buscar trabajo en Internet vaya a garantizarte el éxito, si que al menos estarás evitando echarte tierra encima. No obstante, la realidad es que si eres constante y planificas bien tu búsqueda, tarde o temprano acabarás recogiendo los frutos.

Cómo informar de errores de forma efectiva

[Fuente: http://www.chiark.greenend.org.uk/~sgtatham/bugs-es.html]

por Simon Tatham, programador profesional y de software libre

Cualquiera que haya escrito software para uso público probablemente haya recibido al menos un mal informe de fallo. Informes que no dicen nada (“¡No funciona!”); informes que no tienen sentido; informes que no dan información suficiente; informes que dan información errónea. Informes de problemas que acaban siendo un error del usuario; informes de problemas que acaban siendo un fallo del programa de un tercero; informes de problemas que acaban siendo fallos en la red.

Existe una razón por la cual el soporte técnico se ve como un empleo horrible, y esa razón son los malos informes de fallo. Sin embargo, no todos los informes de fallo son molestos: yo mantengo software libre, cuando no me estoy ganando la vida, y a veces recibo informes de fallos increíblemente claros, útiles e informativos.

En este ensayo intentaré dejar claro lo que hace bueno a un informe de fallo. Idealmente me gustaría que todo el mundo se leyera este ensayo antes de informar de un fallo a cualquiera. Ciertamente, me gustaría que todos los que vayan a informarme de fallos a  se lo leyesen.

En pocas palabras, el objetivo de un informe de fallo es permitir al programador ver el programa fallando ante sus ojos. Puedes mostrárselo en persona, o darle instrucciones cuidadas y detalladas de cómo hacer que falle. Si pueden hacer que falle, podrán intentar recolectar información extra hasta que averigüen la causa. Si no pueden hacer que falle, tendrán que pedirte que tú recolectes esa información en su lugar.

En los informes de fallo, intenta dejar muy claro qué son hechos reales (“Estaba con la computadora y ocurrió esto”) y qué son especulaciones (“Creo que esto puede ser el problema”). Excluye las especulaciones si quieres, pero no excluyas nunca los hechos.

Cuando informas de un fallo, lo haces porque quieres que el fallo se arregle. No tiene sentido blasfemar al programador o ser deliberadamente inútil: puede que sea culpa suya que tú tengas el problema, y puede que tengas razón al estar enfadado con ellos, pero el fallo se arreglará antes si les ayudas proporcionándoles toda la información que necesitan. Recuerda también que si el programa es gratuito, entonces el autor lo proporciona amablemente, de modo que si mucha gente fuera ruda con ellos quizás deban dejar de sentirse amables.

 

“No funciona.”

Dale al programador algo de crédito en cuanto a inteligencia básica: si el programa no funcionase en absoluto, se hubieran dado cuenta. Si no se han dado cuenta, es que en su caso funciona. Por tanto, o bien estás haciendo algo diferente de lo que ellos hacen, o tu entorno es diferente del suyo. Necesitan información; proporcionar esa información es el objetivo de un informe de fallo. Más información casi siempre es mejor que menos.

Muchos programas, particularmente programas gratuitos, publican una lista de fallos conocidos. Si puedes encontrar una lista de fallos conocidos, merece la pena leerla para ver si el fallo que acabas de encontrar ya es conocido o no. Si lo es, probablemente no merezca la pena informar de él nuevamente, pero si piensas que tienes más información que la que aparece en el informe de fallo, puede que quieras contactar con el programador de todos modos. Puede que sean capaces de arreglar el fallo más fácilmente si les das información que todavía no tenían.

Este ensayo está lleno de consejos. Ninguno de ellos es una regla absoluta. Programadores concretos tienen formas concretas en las que les gusta que se les informe de fallos. Si el programa viene con su propio conjunto de consejos para informar de fallos, léelos. Si los consejos que vienen con el programa contradicen los consejos presentes en este ensayo, ¡sigue los que vienen con el programa!

Si no estás informando de un fallo sino simplemente pidiendo ayuda para utilizar el programa, deberías indicar en qué otros sitios has buscado ya la respuesta a tu pregunta. (“Miré el capítulo 4 y la sección 5.2 de la ayuda pero no encontré nada que me dijera si esto es posible.”) Esto permitirá que el programador sepa dónde espera la gente encontrar la respuesta, de forma que pueden hacer que la documentación sea más fácil de usar.

 

“Muéstrame.”

Una de las mejores maneras de informar de un fallo es mostrarlo al programador. Sitúalos delante de tu ordenador, lanza su software, y demuestra aquello que funciona mal. Deja que miren cómo arrancas la máquina, que miren cómo ejecutas el software, que miren cómo interactúas con el software y que miren lo que el software realiza como respuesta a tus entradas.

Conocen su software como la palma de su mano. Saben en qué partes confiar, y saben qué partes pueden tener más fallos. Saben intuitivamente lo que tienen que buscar. Cuando el software haya hecho algo obviamente erróneo, puede que hayan reparado en algo anterior sutilmente erróneo que pueda darles una pista. Pueden observar todo lo que el computador hace durante la ejecución de prueba, y pueden decidir lo que es importante por sí mismos.

Quizás esto no sea suficiente. Quizás decidan que necesitan más información, y te pidan que les muestres lo mismo una vez más. Puede que te pidan que les guíes en el proceso, de forma que puedan reproducir el fallo por sí mismos todas las veces que sean necesarias. Puede que intenten variar el proceso algunas veces más, y así conocer si el problema ocurre sólo en un caso o en una familia de casos relacionados. Si no tienes suerte, quizás necesiten sentarse durante un par de horas con un conjunto de herramientas de desarrollo y empezar a investigar de verdad. Pero lo más importante es que el programador esté mirando el computador cuando algo falla. Una vez que puedan ver el problema, normalmente podrán seguir solos a partir de ese punto para intentar arreglarlo.

 

“Enséñame a mostrar por mí mismo.”

Ésta es la era de Internet. Es la era de las comunicaciones globales. Es la era en la que puedo enviar mi software a alguien de Rusia pulsando un botón, y él puede enviarme sus comentarios de forma igualmente sencilla. Pero si tiene un problema con mi programa, no puede hacer que yo esté presente cuando falla. “Muéstrame” es bueno cuando puedes, pero muchas veces no puedes.

Si tienes que informar de un fallo a un programador que no puede estar presente personalmente, el objetivo del ejercicio es hacer que sean capaces de reproducir el problema. Quieres que el programador ejecute su propia copia del programa, haga lo mismo que tú, y haga que falle de la misma manera. Cuando no pueden ver que el problema ocurre delante de sus ojos, no pueden hacer nada con él.

Así que diles exactamente lo que hiciste. Si es un programa gráfico, diles qué botones pulsaste y en qué orden los pulsaste. Si es un programa que se ejecuta escribiendo una orden, múestrales de forma precisa la orden que usaste. Cuando sea posible, debes proporcionar una transcripción de la sesión, mostrando las órdenes que tecleaste y lo que la computadora mostró como respuesta.

Dale al programador toda la información que se te ocurra. Si el programa lee de un fichero, probablemente necesites enviarles una copia del fichero. Si el programa habla con otro computador a través de una red, probablemente no puedas enviarles una copia de ese computador, pero puedes al menos decir qué clase de computador es y, si es posible, qué software ejecuta.

 

“A mí me funciona. ¿Qué está mal?”

Si le das a un programador una larga lista de entradas y acciones y ellos lanzan su propia copia del programa y no ocurre nada malo, entonces es que no les has dado información suficiente. Posiblemente el fallo no ocurre en todos los computadores; tu sistema y su sistema puede diferir de algún modo. Quizás hayas malentendido lo que el programa supuestamente hace, y ambos estáis mirando exactamente la misma pantalla y tú piensas que está mal y ellos saben que está bien.

Así que describe también lo que ocurrió. Diles exactamente lo que viste. Diles por qué piensas que lo que viste está mal; aún mejor, diles exactamente lo que tú esperabas ver. Si dices “y entonces falló”, estás dejando fuera información muy importante.

Si viste mensajes de error entonces dile al programador, de forma clara y precisa, cuáles eran. ¡Son importantes! En este momento, el programador no está intentando arreglar el problema: sólo están intentando encontrarlo. Necesitan saber qué ha ido mal, y esos mensajes de error son el mayor esfuerzo del computador para decírtelo. Anota los errores si no tienes otra forma más sencilla de recordarlos, pero no merece la pena informar de que el programa generó un error a menos que puedas indicar cuál era el mensaje de error.

En particular, si el mensaje de error contiene números, asegúrate de informar de ellos al programador. Aunque tú no puedas encontrarles sentido no significa que no lo tengan. Los números contienen toda clase de información que puede ser leída por un programador, y probablemente contengan pistas vitales. Los números en los mensajes de error están ahí porque el computador está demasiado confundido como para informar del fallo con palabras, pero está intentando hacerlo lo mejor posible para darte la información importante.

En este punto, el programador está a efectos prácticos realizando el trabajo de un detective. No saben lo que ha ocurrido, y no pueden estar lo bastante cerca como para verlo por ellos mismos, así que están intentando encontrar pistas que les hagan ver el problema. Los mensajes de error, las incomprensibles cadenas de números, e incluso los retardos inesperados son todos tan importantes como las huellas dactilares en la escena de un crimen. ¡Guárdalos!

Si usas Unix, el programa puede producir un volcado de memoria. Los volcados de memoria son una fuente de pistas particularmente buena, así que no los elimines. Por otra parte, a la mayoría de programadores no les gusta recibir ficheros gigantes por correo electrónico sin una advertencia, así que pregunta antes de enviar un volcado a nadie. También, ten en cuenta que los volcados de memoria contienen un registro del estado completo del programa: cualquier “secreto” presente (quizás el programa estuviera manejando un mensaje personal, o trabajando con datos confidenciales) puede aparecer en el fichero del volcado.

 

“Y entonces intenté…”

Hay un montón de cosas que puedes hacer cuando aparece un fallo o un error. Muchas de esas cosas empeoran el problema. Una amiga mía en la escuela borró accidentalmente todos sus documentos de Word, y antes de pedir ayuda a un experto intentó reinstalar el Word y luego ejecutar el desfragmentador de disco. Ninguna de esas acciones ayudó a recuperar sus ficheros, y gracias a ambas el disco se dispersó de tal manera que ningún programa de recuperación hubiese podido hacer nada. Si no hubiese tocado nada, puede que hubiera tenido una oportunidad.

Usuarios como éste son como una mangosta atrapada en una esquina: con su espalda contra la pared y viendo la muerte inminente ante sus ojos, ataca salvajemente, porque hacer algo tiene que ser mejor que no hacer nada. Esto no se adapta bien al tipo de problemas que producen los computadores.

En lugar de ser una mangosta, sé un antílope. Cuando un antílope se enfrenta a algo inesperado o terrorífico, se para. Permanece completamente parado e intenta no atraer la atención, mientras se detiene a pensar y calcular qué es lo mejor que puede hacer. (Si los antílopes tuvieran una línea de atención técnica, probablemente llamarían a ella en ese momento.) Entonces, una vez que ha decidido qué es lo más seguro que puede hacer, lo hace.

Cuando algo va mal, inmediatamente deja de hacer nada. No toques ningún botón en absoluto. Mira la pantalla e intenta encontrar cosas fuera de lo normal, y recuérdalo o anótalo. Entonces quizás empieza cautelosamente a pulsar “Aceptar” o “Cancelar”, lo que te parezca más seguro. Intenta desarrollar un reflejo – si el computador hace algo inesperado, detente.

Si logras salir del problema, bien cerrando el programa afectado o bien reiniciando la computadora, sería bueno intentar hacer que el problema ocurra de nuevo. A los programadores les gustan los problemas que pueden reproducir más de una vez. Los programadores felices arreglan los fallos antes y de forma más eficiente.

 

“Creo que el modulador de taquiones tiene la polarización incorrecta.”

No sólo son los no-programadores los que producen malos informes de fallos. Algunos de los peores informes de fallos que he visto vienen de programadores, e incluso de buenos programadores.

Una vez trabajé con otro programador que no paraba de encontrar fallos en su código e intentaba arreglarlos. De vez en cuando encontraba un fallo que no era capaz de arreglar, y me llamaba para que le ayudase. “¿Qué ha pasado?”, le preguntaba. Él me respondía diciéndome su opinión sobre lo que necesitaba repararse.

Esto funcionaba bien cuando su opinión era correcta. Significaba que ya había hecho la mitad del trabajo y así podíamos terminarlo los dos juntos. Era eficiente y útil.

Sin embargo, muchas veces se equivocaba. Trabajábamos un tiempo intentando averiguar por qué una cierta parte del programa producía datos incorrectos, y eventualmente descubríamos que no los producía, y que habíamos estado media hora investigando un trozo de código que funcionaba perfectamente, y que el problema estaba en otra parte.

Estoy seguro de que tú no harías eso con un doctor. “Doctor, necesito que me prescriba hidroyoyodina.” La gente sabe que no debe hacer eso con un doctor: le describes los síntomas, las molestias y achaques y dolores y erupciones y fiebres, y dejas que el doctor haga el diagnóstico del problema y decida qué hacer al respecto. En otro caso el doctor te tomará por hipocondriaco y lunático, y con razón.

Ocurre lo mismo con los programadores. Proporcionar tu propio diagnóstico puede que a veces sea útil, pero siempre establece los síntomas. El diagnóstico es un extra opcional, y no una alternativa a describir los síntomas. Igualmente, enviar modificaciones del código para arreglar el problema es un suplemento útil en un informe de fallo, pero no un sustituto adecuado para el mismo.

Si un programador te pide información extra, ¡no te la inventes! Una vez alguien me informó de un fallo, y le pedí que ejecutara una cierta orden que yo sabía que fallaría. Le pedí que lo probase porque quería saber cuál de dos errores posibles surgiría. Conocer cuál era una pista vital. Pero no lo intentó – sino que me respondió diciendo “No, eso no va a funcionar”. Me llevó un tiempo persuadirle de que lo intentara de verdad.

Usar tu inteligencia para ayudar al programador está bien. Incluso si tus deducciones son incorrectas, el programador debería estar agradecido de que al menos hayas intentado hacerle la vida más fácil. Pero informa de los síntomas también, o quizás se la compliques.

 

“Vaya, lo hacía hace un momento.”

Dile “fallo intermitente” a un programador y fíjate la cara que ponen. Los problemas fáciles son aquellos en los que la realización de una secuencia simple de acciones hacen que surja el problema. El programador puede repetir esa secuencia de acciones en un entorno de pruebas cerrado y observable y ver lo que ocurre con gran detalle. Demasiados problemas no funcionan así: habrá programas que fallarán una vez a la semana, o una vez cada mucho tiempo, o nunca fallarán cuando los pruebes delante del programador pero sí cuando una fecha límite está a la vuelta de la esquina.

La mayoría de los fallos intermitentes no son verdaderamente intermitentes. La mayoría de ellos tienen alguna lógica en alguna parte. Algunos pueden ocurrir cuando la máquina se está quedando sin memoria, otros pueden ocurrir cuando otro programa intenta modificar un fichero crítico en el momento equivocado, y algunos pueden ocurrir ¡sólo en la primera media hora de cada hora! (Una vez vi uno de éstos).

También, si puedes reproducir el fallo pero el programador no puede, podría ser porque tu computador y su computador son diferentes en algo y ese algo es lo que provoca el fallo. Una vez tuve un programa cuya ventana se enrollaba en una pequeña bola en la esquina de la pantalla, se quedaba ahí y se enfurruñaba. Pero sólo hacía eso en pantallas de 800×600; en mi pantalla de 1024×768 estaba bien.

El programador querrá saber todo lo que puedas contarle del problema. Pruébalo en otra máquina, quizás. Pruébalo dos o tres veces y mira la frecuencia con la que falla. Si falla cuando estás trabajando en algo serio pero no cuando estás intentando demostrarlo, puede que sean los tiempos grandes de ejecución o ficheros grandes lo que lo hagan fallar. Intenta recordar todos los detalles que puedas acerca de lo que estabas haciendo cuando el programa falló, y si encontraste algún tipo de patrón, menciónalo. Cualquier información que puedas proporcionar será útil. Incluso si es sólo probabilística (como “falla con más frecuencia si estoy ejecutando el Emacs”), puede que no proporcione pistas directas acerca de la causa del problema, pero puede que ayude al programador a la hora de reproducirlo.

Más importante, el programador querrá estar seguro de si es un auténtico fallo intermitente o un fallo específico de esa máquina. Querrán conocer un montón de detalles acerca de tu computador, para intentar saber cómo difiere del suyo. Muchos de esos detalles dependerán del programa en particular, pero algo que deberías estar listo para proporcionar son los números de versión. El número de versión del propio programa, el número de versión del sistema operativo, y probablemente de cualquier otro programa que intervenga en el problema.

“Entonces cargué el disco en Windows…”

Escribir de forma clara es esencial en un informe de fallo. Si el programador no puede entenderte, quizás sea mejor no decir nada.

Recibo informes de fallos de muchas partes del mundo. Muchos de ellos de personas que no hablan inglés nativamente, y muchos de esos se disculpan por su pobre nivel de inglés. En general, los informes con disculpas por el pobre nivel de inglés son en realidad muy claros y útiles. La mayoría de informes confusos provienen de hablantes nativos de inglés que suponen que les entenderé aunque no hagan ningún esfuerzo por ser claros o precisos.

  • Sé específico. Si puedes hacer lo mismo de dos maneras, di cuál usaste. “Seleccioné Cargar” puede significar “Pulsé sobre Cargar” o “Pulsé Alt+L”. Di cuál usaste. A veces importa.
  • Se prolijo. Da más información en lugar de menos. Si dices muchas cosas, el programador puede ignorar parte de ellas. Si dices pocas, tienen que hacerte más preguntas. Una vez recibí un informe de fallo de una sola frase; cada vez que preguntaba más información, el informador respondía con otra frase suelta. Me llevó varias semanas obtener un volumen de información útil, porque respondía con una frase corta de cada vez.
  • Ten cuidado con los pronombres y los verbos sin sujeto. No uses referencias como “la ventana”, cuando no está claro lo que significa. Considera el siguiente ejemplo: “Lancé la AplicaciónCualquiera. Apareció una ventana con una advertencia. Intenté cerrarla y cascó.” No está claro lo que el usuario intentó cerrar. ¿Intentó cerrar la ventana de advertencia o la ventana de AplicaciónCualquiera? Hay una diferencia. En lugar de eso, podría decir “Lancé la AplicaciónCualquiera, la cual mostró una ventana de advertencia. Intenté cerrar la ventana de advertencia y AplicaciónCualquiera cascó.” Esto es más largo y repetitivo, pero es más claro y más difícil de malinterpretar.
  • Lee lo que has escrito. Léete el informe a ti mismo e intenta ver si  crees que es claro. Si listas una secuencia de acciones a realizar para provocar el fallo, intenta seguirlas tú mismo para comprobar si has omitido algún paso.

Resumen

  • El primer objetivo de un informe de fallo es permitir que el programador vea el fallo por sí mismo. Si no puedes hacer que el programa falle delante de ellos, dale instrucciones detalladas para que ellos mismos puedan hacer que falle.
  • Si esto no surte efecto, y el programador no puede verlo fallar por sí mismo, el segundo objetivo del informe de fallo es describir lo que falló. Describe todo en detalle. Describe lo que viste, y lo que esperabas ver. Toma nota de los mensajes de error, especialmente cuando contengan números.
  • Cuando el computador haga algo inesperado, detente. No hagas nada hasta que estés tranquilo, y no hagas nada que creas que es peligroso.
  • Por todos los medios, intenta diagnosticar el problema tú mismo si crees que puedes, pero si lo haces, informa también de los síntomas igualmente.
  • Prepárate para proporcionar información extra si el programador la necesita. Si no la necesitasen no preguntarían por ella. No es que estén siendo retorcidos. Ten los números de versión preparados, porque probablemente harán falta.
  • Escribe de manera clara. Di lo que quieres decir, y asegúrate de que no se puede malinterpretar.
  • Por encima de todo, sé preciso. A los programadores les gusta la precisión.

Abstract Factory Design Pattern in Java

[Fuente: http://www.journaldev.com/1418/abstract-factory-design-pattern-in-java]

 

Abstract Factory is one of the Creational pattern and almost similar to Factory Pattern except the fact that its more like factory of factories.

If you are familiar with factory design pattern in java, you will notice that we have a single Factory class that returns the different sub-classes based on the input provided and factory class uses if-else or switch statement to achieve this.

In Abstract Factory pattern, we get rid of if-else block and have a factory class for each sub-class and then an Abstract Factory class that will return the sub-class based on the input factory class. At first it seems confusing but once you see the implementation, its really easy to grasp and understand the minor difference between Factory and Abstract Factory pattern.

Like our factory pattern post, we will use the same super class and sub-classes.

Super Class and Sub-Classes

Computer.java
package com.journaldev.design.model;  
public abstract class Computer {
      
    public abstract String getRAM();
    public abstract String getHDD();
    public abstract String getCPU();
      
    @Override
    public String toString(){
        return "RAM= "+this.getRAM()+", HDD="+this.getHDD()+", CPU="+this.getCPU();
    }
}
PC.java
package com.journaldev.design.model;   
public class PC extends Computer {
  
    private String ram;
    private String hdd;
    private String cpu;
      
    public PC(String ram, String hdd, String cpu){
        this.ram=ram;
        this.hdd=hdd;
        this.cpu=cpu;
    }
    @Override
    public String getRAM() {
        return this.ram;
    }
  
    @Override
    public String getHDD() {
        return this.hdd;
    }
  
    @Override
    public String getCPU() {
        return this.cpu;
    }
  
}
Server.java
package com.journaldev.design.model;    
public class Server extends Computer {
  
    private String ram;
    private String hdd;
    private String cpu;
      
    public Server(String ram, String hdd, String cpu){
        this.ram=ram;
        this.hdd=hdd;
        this.cpu=cpu;
    }
    @Override
    public String getRAM() {
        return this.ram;
    }
  
    @Override
    public String getHDD() {
        return this.hdd;
    }
  
    @Override
    public String getCPU() {
        return this.cpu;
    }
  
}

Factory Classes for Each sub-class

First of all we need to create a Abstract Factory interface or abstract class.

ComputerAbstractFactory.java
package com.journaldev.design.abstractfactory;
 
import com.journaldev.design.model.Computer;
 
public interface ComputerAbstractFactory {
 
    public Computer createComputer();
 
}

Notice that createComputer() method is returning an instance of super class Computer. Now our factory classes will implement this interface and return their respective sub-class.

PCFactory.java
package com.journaldev.design.abstractfactory;
 
import com.journaldev.design.model.Computer;
import com.journaldev.design.model.PC;
 
public class PCFactory implements ComputerAbstractFactory {
 
    private String ram;
    private String hdd;
    private String cpu;
     
    public PCFactory(String ram, String hdd, String cpu){
        this.ram=ram;
        this.hdd=hdd;
        this.cpu=cpu;
    }
    @Override
    public Computer createComputer() {
        return new PC(ram,hdd,cpu);
    }
 
}

Similarly we will have a factory class for Server sub-class.

 
ServerFactory.java
package com.journaldev.design.abstractfactory;
 
import com.journaldev.design.model.Computer;
import com.journaldev.design.model.Server;
 
public class ServerFactory implements ComputerAbstractFactory {
 
    private String ram;
    private String hdd;
    private String cpu;
     
    public ServerFactory(String ram, String hdd, String cpu){
        this.ram=ram;
        this.hdd=hdd;
        this.cpu=cpu;
    }
     
    @Override
    public Computer createComputer() {
        return new Server(ram,hdd,cpu);
    }
 
}

Now we will create a consumer class that will provide the entry point for the client classes to create sub-classes.

ComputerFactory.java
package com.journaldev.design.abstractfactory;
 
import com.journaldev.design.model.Computer;
 
public class ComputerFactory {
 
    public static Computer getComputer(ComputerAbstractFactory factory){
        return factory.createComputer();
    }
}

Notice that its a simple class and getComputer method is accepting ComputerAbstractFactory argument and returning Computer object. At this point the implementation must be getting clear.

Lets write a simple test method and see how to use the abstract factory to get the instance of sub-classes.

TestDesignPatterns.java
package com.journaldev.design.test;
 
import com.journaldev.design.abstractfactory.PCFactory;
import com.journaldev.design.abstractfactory.ServerFactory;
import com.journaldev.design.factory.ComputerFactory;
import com.journaldev.design.model.Computer;
 
public class TestDesignPatterns {
 
    public static void main(String[] args) {
        testAbstractFactory();
    }
 
    private static void testAbstractFactory() {
        Computer pc = com.journaldev.design.abstractfactory.ComputerFactory.getComputer(new PCFactory("2 GB","500 GB","2.4 GHz"));
        Computer server = com.journaldev.design.abstractfactory.ComputerFactory.getComputer(new ServerFactory("16 GB","1 TB","2.9 GHz"));
        System.out.println("AbstractFactory PC Config::"+pc);
        System.out.println("AbstractFactory Server Config::"+server);
    }
}

Output of the above program will be:

1
2
AbstractFactory PC Config::RAM= 2 GB, HDD=500 GB, CPU=2.4 GHz
AbstractFactory Server Config::RAM= 16 GB, HDD=1 TB, CPU=2.9 GHz

Here is the class diagram of abstract factory implementation.

Abstract-Factory-Pattern

Benefits of Abstract Factory Pattern

  • Abstract Factory pattern provides approach to code for interface rather than implementation.
  • Abstract Factory pattern is “factory of factories” and can be easily extended to accommodate more products, for example we can add another sub-class Laptop and a factory LaptopFactory.
  • Abstract Factory pattern is robust and avoid conditional logic of Factory pattern.

Abstract Factory Pattern Examples in JDK

  • javax.xml.parsers.DocumentBuilderFactory#newInstance()
  • javax.xml.transform.TransformerFactory#newInstance()
  • javax.xml.xpath.XPathFactory#newInstance()

Factory Design Pattern

 

Factory Pattern is one of the Creational Design pattern and it’s widely used in JDK as well as frameworks like Spring and Struts.

Factory design pattern is used when we have a super class with multiple sub-classes and based on input, we need to return one of the sub-class. This pattern take out the responsibility of instantiation of a class from client program to the factory class. Let’s first learn how to implement factory pattern in java and then we will learn it’s benefits and we will see its usage in JDK.

Super Class

Super class in factory pattern can be an interface, abstract class or a normal java class. For our example, we have super class as abstract class with overridden toString() method for testing purpose.

Computer.java
   
package com.journaldev.design.model;

public abstract class Computer {

public abstract String getRAM();
public abstract String getHDD();
public abstract String getCPU();

@Override
public String toString(){
return "RAM= "+this.getRAM()+", HDD="+this.getHDD()+", CPU="+this.getCPU();
}
}

Sub Classes

Let’s say we have two sub-classes PC and Server with below implementation.

PC.java
   
package com.journaldev.design.model;


public class PC extends Computer {

private String ram;
private String hdd;
private String cpu;

public PC(String ram, String hdd, String cpu){
this.ram=ram;
this.hdd=hdd;
this.cpu=cpu;
}
@Override
public String getRAM() {
return this.ram;
}

@Override
public String getHDD() {
return this.hdd;
}

@Override
public String getCPU() {
return this.cpu;
}

}

Notice that both the classes are extending Computer class.

Server.java
   
package com.journaldev.design.model;


public class Server extends Computer {

private String ram;
private String hdd;
private String cpu;

public Server(String ram, String hdd, String cpu){
this.ram=ram;
this.hdd=hdd;
this.cpu=cpu;
}
@Override
public String getRAM() {
return this.ram;
}

@Override
public String getHDD() {
return this.hdd;
}

@Override
public String getCPU() {
return this.cpu;
}

}

Factory Class

Now that we have super classes and sub-classes ready, we can write our factory class. Here is the basic implementation.

 
ComputerFactory.java
   
package com.journaldev.design.factory;

import com.journaldev.design.model.Computer;
import com.journaldev.design.model.PC;
import com.journaldev.design.model.Server;

public class ComputerFactory {

public static Computer getComputer(String type, String ram, String hdd, String cpu){
if("PC".equalsIgnoreCase(type)) return new PC(ram, hdd, cpu);
else if("Server".equalsIgnoreCase(type)) return new Server(ram, hdd, cpu);

return null;
}
}
  1. We can keep Factory class Singleton or we can keep the method that returns the subclass as static.
  2. Notice that based on the input parameter, different subclass is created and returned.

factory-pattern-java

Here is a simple test client program that uses above factory pattern implementation.

TestFactory.java
   
package com.journaldev.design.test;

import com.journaldev.design.abstractfactory.PCFactory;
import com.journaldev.design.abstractfactory.ServerFactory;
import com.journaldev.design.factory.ComputerFactory;
import com.journaldev.design.model.Computer;

public class TestFactory {

public static void main(String[] args) {
Computer pc = ComputerFactory.getComputer("pc","2 GB","500 GB","2.4 GHz");
Computer server = ComputerFactory.getComputer("server","16 GB","1 TB","2.9 GHz");
System.out.println("Factory PC Config::"+pc);
System.out.println("Factory Server Config::"+server);
}

}

Output of above program is:

1
2
Factory PC Config::RAM= 2 GB, HDD=500 GB, CPU=2.4 GHz
Factory Server Config::RAM= 16 GB, HDD=1 TB, CPU=2.9 GHz

Benefits of Factory Pattern

  1. Factory pattern provides approach to code for interface rather than implementation.
  2. Factory pattern removes the instantiation of actual implementation classes from client code, making it more robust, less coupled and easy to extend. For example, we can easily change PC class implementation because client program is unaware of this.
  3. Factory pattern provides abstraction between implementation and client classes through inheritance.

Factory Pattern Examples in JDK

  1. java.util.Calendar, ResourceBundle and NumberFormat  getInstance() methods uses Factory pattern.
  2. valueOf() method in wrapper classes like Boolean, Integer etc.
 

Java Singleton Design Pattern Best Practices with Examples

[Fuente :http://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-with-examples]

Singleton is one of the Gangs of Four Design patterns and comes in the Creational Design Pattern category. From the definition, it seems to be a very simple design pattern but when it comes to implementation, it comes with a lot of implementation concerns. The implementation of Singleton pattern has always been a controversial topic among developers. Here we will learn about Singleton design pattern principles, different ways to implement Singleton and some of the best practices for it’s usage.

Singleton Pattern

Singleton pattern restricts the instantiation of a class and ensures that only one instance of the class exists in the java virtual machine. The singleton class must provide a global access point to get the instance of the class. Singleton pattern is used for logging, drivers objects, caching and thread pool.

Singleton design pattern is also used in other design patterns like Abstract FactoryBuilderPrototype,Facade etc. Singleton design pattern is used in core java classes also, for example java.lang.Runtime,java.awt.Desktop.

Java Singleton Pattern

To implement Singleton pattern, we have different approaches but all of them have following common concepts.

  • Private constructor to restrict instantiation of the class from other classes.
  • Private static variable of the same class that is the only instance of the class.
  • Public static method that returns the instance of the class, this is the global access point for outer world to get the instance of the singleton class.

In further sections, we will learn different approaches of Singleton pattern implementation and design concerns with the implementation.

  1. Eager initialization
  2. Static block initialization
  3. Lazy Initialization
  4. Thread Safe Singleton
  5. Bill Pugh Singleton Implementation
  6. Using Reflection to destroy Singleton Pattern
  7. Enum Singleton
  8. Serialization and Singleton

Eager initialization

In eager initialization, the instance of Singleton Class is created at the time of class loading, this is the easiest method to create a singleton class but it has a drawback that instance is created even though client application might not be using it.

Here is the implementation of static initialization singleton class.

EagerInitializedSingleton.java
package com.journaldev.singleton;

public class EagerInitializedSingleton {

    private static final EagerInitializedSingleton instance = new EagerInitializedSingleton();

    //private constructor to avoid client applications to use constructor
    private EagerInitializedSingleton(){}

    public static EagerInitializedSingleton getInstance(){
        return instance;
    }
}

If your singleton class is not using a lot of resources, this is the approach to use. But in most of the scenarios, Singleton classes are created for resources such as File System, Database connections etc and we should avoid the instantiation until unless client calls the getInstance method. Also this method doesn’t provide any options for exception handling.

Static block initialization

Static block initialization implementation is similar to eager initialization, except that instance of class is created in the static block that provides option for exception handling.

StaticBlockSingleton.java
package com.journaldev.singleton;

public class StaticBlockSingleton {

    private static StaticBlockSingleton instance;

    private StaticBlockSingleton(){}

    //static block initialization for exception handling
    static{
        try{
            instance = new StaticBlockSingleton();
        }catch(Exception e){
            throw new RuntimeException("Exception occured in creating singleton instance");
        }
    }

    public static StaticBlockSingleton getInstance(){
        return instance;
    }
}

Both eager initialization and static block initialization creates the instance even before it’s being used and that is not the best practice to use. So in further sections, we will learn how to create Singleton class that supports lazy initialization.

Read: Java static

Lazy Initialization

Lazy initialization method to implement Singleton pattern creates the instance in the global access method. Here is the sample code for creating Singleton class with this approach.

LazyInitializedSingleton.java
package com.journaldev.singleton;

public class LazyInitializedSingleton {

    private static LazyInitializedSingleton instance;

    private LazyInitializedSingleton(){}

    public static LazyInitializedSingleton getInstance(){
        if(instance == null){
            instance = new LazyInitializedSingleton();
        }
        return instance;
    }
}

The above implementation works fine incase of single threaded environment but when it comes to multithreaded systems, it can cause issues if multiple threads are inside the if loop at the same time. It will destroy the singleton pattern and both threads will get the different instances of singleton class. In next section, we will see different ways to create a thread-safe singleton class.

Thread Safe Singleton

The easier way to create a thread-safe singleton class is to make the global access method synchronized, so that only one thread can execute this method at a time. General implementation of this approach is like the below class.

ThreadSafeSingleton.java
package com.journaldev.singleton;

public class ThreadSafeSingleton {

    private static ThreadSafeSingleton instance;

    private ThreadSafeSingleton(){}

    public static synchronized ThreadSafeSingleton getInstance(){
        if(instance == null){
            instance = new ThreadSafeSingleton();
        }
        return instance;
    }

}

Above implementation works fine and provides thread-safety but it reduces the performance because of cost associated with the synchronized method, although we need it only for the first few threads who might create the separate instances (Read: Java Synchronization). To avoid this extra overhead every time,double checked locking principle is used. In this approach, the synchronized block is used inside the if condition with an additional check to ensure that only one instance of singleton class is created.

Below code snippet provides the double checked locking implementation.
public static ThreadSafeSingleton getInstanceUsingDoubleLocking(){
    if(instance == null){
        synchronized (ThreadSafeSingleton.class) {
            if(instance == null){
                instance = new ThreadSafeSingleton();
            }
        }
    }
    return instance;
}

Read: Thread Safe Singleton Class

Bill Pugh Singleton Implementation

Prior to Java 5, java memory model had a lot of issues and above approaches used to fail in certain scenarios where too many threads try to get the instance of the Singleton class simultaneously. So Bill Pugh came up with a different approach to create the Singleton class using a inner static helper class. The Bill Pugh Singleton implementation goes like this;

BillPughSingleton.java
package com.journaldev.singleton;

public class BillPughSingleton {

    private BillPughSingleton(){}

    private static class SingletonHelper{
        private static final BillPughSingleton INSTANCE = new BillPughSingleton();
    }

    public static BillPughSingleton getInstance(){
        return SingletonHelper.INSTANCE;
    }
}

Notice the private inner static class that contains the instance of the singleton class. When the singleton class is loaded, SingletonHelper class is not loaded into memory and only when someone calls the getInstance method, this class gets loaded and creates the Singleton class instance.

This is the most widely used approach for Singleton class as it doesn’t require synchronization. I am using this approach in many of my projects and it’s easy to understand and implement also.

Read: Java Nested Classes

Using Reflection to destroy Singleton Pattern

Reflection can be used to destroy all the above singleton implementation approaches. Let’s see this with an example class.

ReflectionSingletonTest.java
package com.journaldev.singleton;

import java.lang.reflect.Constructor;

public class ReflectionSingletonTest {

    public static void main(String[] args) {
        EagerInitializedSingleton instanceOne = EagerInitializedSingleton.getInstance();
        EagerInitializedSingleton instanceTwo = null;
        try {
            Constructor[] constructors = EagerInitializedSingleton.class.getDeclaredConstructors();
            for (Constructor constructor : constructors) {
                //Below code will destroy the singleton pattern
                constructor.setAccessible(true);
                instanceTwo = (EagerInitializedSingleton) constructor.newInstance();
                break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(instanceOne.hashCode());
        System.out.println(instanceTwo.hashCode());
    }

}

When you run the above test class, you will notice that hashCode of both the instances are not same that destroys the singleton pattern. Reflection is very powerful and used in a lot of frameworks like Spring and Hibernate, do check out Java Reflection Tutorial.

Enum Singleton

To overcome this situation with Reflection, Joshua Bloch suggests the use of Enum to implement Singleton design pattern as Java ensures that any enum value is instantiated only once in a Java program. Since Java Enum values are globally accessible, so is the singleton. The drawback is that the enum type is somewhat inflexible; for example, it does not allow lazy initialization.

EnumSingleton.java
package com.journaldev.singleton;

public enum EnumSingleton {

    INSTANCE;

    public static void doSomething(){
        //do something
    }
}

Read: Java Enum

Serialization and Singleton

Sometimes in distributed systems, we need to implement Serializable interface in Singleton class so that we can store it’s state in file system and retrieve it at later point of time. Here is a small singleton class that implements Serializable interface also.

SerializedSingleton.java
package com.journaldev.singleton;

import java.io.Serializable;

public class SerializedSingleton implements Serializable{

    private static final long serialVersionUID = -7604766932017737115L;

    private SerializedSingleton(){}

    private static class SingletonHelper{
        private static final SerializedSingleton instance = new SerializedSingleton();
    }

    public static SerializedSingleton getInstance(){
        return SingletonHelper.instance;
    }

}

The problem with above serialized singleton class is that whenever we deserialize it, it will create a new instance of the class. Let’s see it with a simple program.

SingletonSerializedTest.java
package com.journaldev.singleton;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

public class SingletonSerializedTest {

    public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
        SerializedSingleton instanceOne = SerializedSingleton.getInstance();
        ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
                "filename.ser"));
        out.writeObject(instanceOne);
        out.close();

        //deserailize from file to object
        ObjectInput in = new ObjectInputStream(new FileInputStream(
                "filename.ser"));
        SerializedSingleton instanceTwo = (SerializedSingleton) in.readObject();
        in.close();

        System.out.println("instanceOne hashCode="+instanceOne.hashCode());
        System.out.println("instanceTwo hashCode="+instanceTwo.hashCode());

    }

}

Output of the above program is;

1
2
instanceOne hashCode=2011117821
instanceTwo hashCode=109647522

So it destroys the singleton pattern, to overcome this scenario all we need to do it provide the implementation of readResolve() method.

protected Object readResolve() {
    return getInstance();
}

After this you will notice that hashCode of both the instances are same in test program.

Read: Java Serialization and Java Deserialization.

I hope this article helps you in grasping fine details of Singleton design pattern, do let me know through your thoughts and comments.

Java Design Patterns – Tutorial con ejemplos

[Fuente: http://www.journaldev.com/1827/]

java-design-patternsLos patrones de diseño son muy populares entre los programadores de software.

  • Un patrón de diseño es una solución bien descrita a un problema común de software.
  • Algunos de los beneficios de utilizar patrones de diseño son:
    • Los patrones de diseño están ya definidos y proporcionados como estándares por la industria para resolver problemas recurrentes, de forma que ahora mucho tiempo.
    • Utilizar patrones de diseño promociona reusabilidad lo cual produce un código más mantenible , robusto y reusable. Ayuda a reducir el total cost of ownership (TCO) of the software product.
    • Ya que los patrones de diseño están ya definidos, hace nuestro código más fácil de entender y depurar. Esto lleva a un desarrollo más rápido y a que si se incorporan nuevos miembros a un equipo les sea fácil entender el código.
  • Los patrones de diseño Java se dividen en tres categorías: creacionales (creational) , estructurales (structural) y de comportamiento (behavioral).En este post haremos un índice a artículos sobre patrones de diseño publicados en otros post.

Creational Design Patterns

Los patrones de diseño creacionales proporcionan una solución para instanciar un objeto de la mejor manera posible en situaciones específicas.

Singleton

El patrón singleton restringe la instanciación de una clase de forma que asegura que solo una instancia de la clase existe en la JVM. Parece un patrón de diseño muy simple pero cuando hay que implementarlo , viene con varios aspectos de implementación a considerar. La implementación de un patrón Singleton supone siempre un tema controvertido entre los programadores. Visita Singleton Design Pattern para aprender más sobre las diferentes formas de implementar este patrón y los pros y las contras de cada uno de los métodos.

Factory

El patrón Factory se utiliza cuando tenemos una super clase con múltiples subclasses y , basándose en la entrada del usuario , necesitamos retornar una de las subclases. Este patrón le da la responsabilidad de la instanciación de una clase del programa cliente a la clase factory. Podemos aplicar el patrón Singleton en la clase Factory o hacer el método factory estático. Visita Factory Design Pattern para ver un ejemplo de un programa y los beneficios de este patrón.

Abstract Factory

El patrón Abstract Factory es similar al patrón Factory ya que es como una factoria de factorias. Si ya conoces el patrón factory en Java , te darás cuenta que tenemos una sola Factory class que retorna las diferentes subclases basandose en la entrada del usuario. La factory class utiliza if-else o la sentencia switch para conseguir esto.

En el patrón Abstract Factory , evitamos los bloques if-else y lo que se hace es tener una factory class por cada subclase y entonces una clase Abstract Factory que retornará la subclase basándose en la factory class de entrada. Visita Abstract Factory Pattern  para conocer cómo se implementa con un programa de ejemplo.

Builder 

Este patrón fue introducido para resolver algunos de los problemas con Factory y Abstract Factory cuando el Object contiene muchos atributos. El patrón Builder resuelve el problema de tener un grán número de parámetros opcionales y estado inconsistente proporcionando una forma de construir el objeto paso a paso y proporcionar un método que retornará el objeto final. Visita Builder Pattern para ver un programa de ejemplo y las clases utilizadas en el JDK.

Prototype 

El patrón Prototipo se utiliza cuando la creación del objeto es un asunto de mucho coste y requiere mucho tiempo y recursos y además tienes un objeto similar ya existente. Así este patrón proporciona un mecanismo para copiar el objeto original a un nuevo objeto y entonces modificarlo de acuerdo a nuestras necesidades. Este patrón utilizar java cloning para copiar el objeto.

Este patrón de diseño obliga a que el objeto que estás copiando debe proporcionar un método de copiado. El copiado no debe ser hecho por otra clase. Sin embargo sobre si utilizar shallow copy o deep copy de las properties del Object depende de los requerimientos y es una decisión de diseño. Visita Prototype Pattern para ver un programa de ejemplo.

Structural Design Patterns

Los patrones estructurales proporcionan distintas formas de crear una estructura de clase, por ejemplo utilizar herencia y composición para crear un objeto grande de objetos pequeños.

Adapter 

El patrón Adapter es utilizado para cuando dos interfaces sin relación tienen que trabajar juntos. El objeto que une estos interfaces se le llama un Adapter. Como ejemplo de la vida real, podemos pensar en un cargador de móvil como un adapter porque la batería del móvil necesita 3 voltios para cargar pero el enchufe normal tiene 120 voltios de salida (EEUU) y 240V (Europa y la India). Asi que el cargador de un móvil funciona como un adapter entre el conector de carga del móvil y el enchufe de la pared. Visita Adapter Pattern  para ver un programa de ejemplo.

Composite 

El patrón composite es uno de los patrones estructurales y es utilizado cuando tenemos que representar una jerarquía part-whole. Cuando tenemos que crear una estructura en la forma de que los objetos de la estructura deben ser tratados de la misma forma, podemos aplicar este patrón.

Lo entenderemos con un ejemplo de la vida real – Un diagrama es una estructura que se compone de Objects como Circle, Lines, Triangles etc y cuando coloreamos (por ejemplo de Red), el mismo color debe ser aplicado a todos los Objects del dibujo. Aquí dibujar es hecho de distintas partes y todos ellos tienen las mismas operaciones. Visita Composite Pattern  para ver distintos componentes de composite y un programa de ejemplo.

Proxy 

Este patrón pretende “Proporcionar un sustituto de otro objeto para controlar el acceso a este“. La definición en si misma es muy clara de forma que se usa este patrón cuando queremos proporcionar acceso controlado de una funcionalidad.

Digamos que tenemos una clase que puede ejecuta algún comando en el sistema. Ahora si estamos utilizándolo, imaginemos que queremos dar este programa a una aplicación cliente, puede haber entonces varios problemas gordos cuando el programa cliente puede facilitar comandos para borrar ficheros del sistema o cambiar algunas settings que no son deseables. Visita Proxy Pattern para ver más detalles.

Flyweight 

Este patrón es utilizado cuando necesitamos crear varios Objects de una clase. Ya que cada objeto consume espacio de memoria que puede ser crucial para dispositivos con pocos recursos de memoria, como por ejemplo dispositivos móviles, el patrón flyweight puede ser apli Flyweight Pattern .

Facade 

El patrón Facade es utilizado para ayudar a las aplicaciones cliente interactuen fácilmente con el sistema. Supongamos que tenemos una aplicación con un conjunto de interfaces para utilizar bases de datos Mysql / Oracle y generar distintos tipos de informes, como por ejemplo un informe HTML , un PDF , etc. Asi tenemos varis conjuntos de interfaces con distintos tipos de bases de datos. Ahora una aplicación cliente puede utilizar estos interfaces para pedir conexión a la base de datos y generar informes. Pero cuando la complejidad se incrementa o los nombres de los interfaces son confusos, la aplicación cliente encontrará difícil utilizarlos. Asi podemos aplicar el patrón Facade para un proporcionar un wrapper interface encima del interface existente para ayudar a la aplicación cliente. Visita el Facade Pattern para ver detalles de implementación y programa de ejemplo.

Bridge 

Cuando tenemos jerarquías de interfaces tanto en interfaces como en implementaciones, entonces el patrón Builder se utiliza para desacoplar los interfaces de la implementación y esconder los detalles de implementación a los programas cliente. Como el patrón Adapter, es uno de los patrones estructurales.La implementación del patrón Bridge sigue la noción de preferir Composition sobre la herencia. Visita Bridge Pattern para más detalles de implementación y un programa de ejemplo.

Decorator 

El patrón Decorator se utiliza para modificar la funcionalidad de un objeto en tiempo de ejecución. Al mismo tiempo otras instancias de la misma clase no serán afectados por esto, así que el objeto individual condigue realizar el comportamiento modificado. El patrón Decorator es uno de los patrones estructurales y utiliza las abstract classes o los interfaces con la composition para ser implementado.

Utilizamos herencia o composition para extender el comportamiento de un objeto pero esto es hecho en tiempo de compilación y es aplicable a todas las instancias de la clase. No podemos añadir ninguna nueva funcionalidad o borrar alguna existente en tiempo de ejecución – aqui es donde el patrón Decorator entra en escena. Visita Decorator Pattern para ver un ejemplo de programa y detalles de implementación.

Behavioral Design Patterns

Los patrones de comportamiento proporcionan solución para que haya mejor interacción entre los objetos y como proporcionar poco acople y flexibilidad se haga de forma fácil.

Template Method

  • El template Method es utilizado para crear un método stub y delegar algunos de los pasos de la implementación a las subclases. El Template method define los pasos para ejecutar un algoritmo y puede proporcionar una implementación por defecto que podría ser común a todas o a algunas de las subclases.

Supongamos que queremos proporcionar un algoritmo para construir una casa. Los pasos necesarios a ser realizados para construir una casa son  – construir el diseño , construir los pilares , construir los muros y las ventanas. El punto importante es que no podemos cambiar el orden de ejecución porque no podemos poner las ventanas antes de construir la base. asi que en este caso podemos crear un template method que usará distintos métodos para construir la casa. Visita Template Method Pattern para ver más detalles de implementación.

Mediator 

  • El patrón Mediator se utiliza para proporcionar un medio de comunicación centralizada entre distintos objetos en un sistema. Estos patrones de diseño son muy útiles cuando en una aplicación corporativa hay varios objetos que están interactuando los unos con los otros. Si los objetos interactuan entre ellos directamente, los componentes del sistema quedan muy acoplados entre llos lo que hace que la mantenibilidad sea costosa y muy poco flexible de extender. El patrón Mediator se enfoca en proporcionar un mediator entre los objetos para que se comuniquen y les ayuda a tener poco acoplamiento entre ellos.

Los controladores aereos son un grans ejemplo de mediator donde la torre de control funciona como un mediator para que exista comunicación entre los distintos vuelos. Mediator funciona como un router entre objetos y puede tener su propia lógica para proporcionar una forma de comunicación determinada. Visita Mediator Pattern para más detalles.

Chain of Responsibility 

Este patrón se utiliza para conseguir desacople en el diseño de un software donde una request de un cliente es pasada a una cadena de objetos para que sea procesada. Entonces el objeto de la cadena decide cada uno por si mismo quien procesará la request y si la request requiere ser enviada al siguiente objeto de la cadena o no.

Sabemos que tenemos varios catch blocks en un bloque de código try-catch. Aquí cada bloque catch es como un procesador que procesa una excepción en particular. así cuando cualquier excepción ocurre en el bloque try, es enviada al promer bloque catch para que sea procesada. Si ese catch block no puede procesarla, la pasa la siguiente objeto de la cadena, es decir el siguiente bloque catch. Si incluso el último bloque catch de la cadena no puede procesar la excepción, la excepción es enviada fuera de la cadena del programa que invoca.

Los cajeros automáticos (ATM) pueden ser implementadas utilizando Chain of Responsibility Pattern, visita ese link para más detalles.

Observer 

El patrón Observer es útil cuando estás interesado en el estado de un objeto y queremos ser notificados cuando haya algún cambio. En este patrón , el objeto que observa el estado de otro objeto es llamado el Observer y el objeto siendo observado el Subject.

Java proporciona en su core la implementación de Observer a través de la clase java.util.Observable y el interfaz java.util.Observer.Sin embargo no es ampliamente utilizado porque la implementación es muy simple y la mayoría de las veces no queremos finalizar ampliando una clase solo para implementar el patrón Observer ya que java no proporciona herencia múltiple en las clases.

El  Java Message Service (JMS) utiliza Observer junto con el patrón Mediator para permitir a las aplicaciones suscribirse y publicar datos en otras aplicaciones. Visita Observer Pattern para más detalles y un ejemplo de implementación.

Strategy 

El patrón Strategy se utiliza cuando tenemos varios algoritmos para realizar una tarea específica y el cliente decide qué implementación va a ser utilizada en tiempo de ejecución.

El patrón Strategy también es conocido como el patrón Policy. Definimos varios algoritmos y permite a una aplicación cliente pasar el algoritmo a ser utilizado como un parámetro. Uno de los mejores ejemplos de este patrón es el método Collections.sort() que recibe el parámetro Comparator. Basándose en las implementaciones distintas de los interfaces Comparator , los objetos son ordenados de distintas formas. Visita Strategy Pattern para más detalles.

Command 

Este patrón se utiliza para implementar desacople en un modelo de request-response. En este patrón, la request se envía al invocador y es el invocador el que la pasa al objeto Command encapsulado. El objeto Command pasa la request al método apropiado del Receiver para realizar la acción específica.

Digamos quee queremos proporcionar una utilizada de sistema de ficheros con métodos para abrir , escribir y cerrar ficheros y que debe funcionar para múltiples sistemas operativos tales como Windows o unix.

Para implementar nuestra utilidad de File System , lo primero de todo que necesitamos es crear las clases receiver que harán todo el trabajo. Ya que codificamos en términos de interfaces java, podemos tener un interfaz FileSystemReceiver y sus clases de implementación para distintos sistemas operativos. Visita  Command Pattern para más detalles.

State 

El patrón de State se utiliza cuando un objeto cambia su comportamiento basándose en su estado interno.

Si tenemos que cambiar el comportamiento de un objeto basándose en su estado , podemos tener una variable de estado en el Object y utilizar un bloque de condiciones if-else para realizar diferentes acciones basadas en el estado. Este patrón se utiliza para proporcionar un forma sistematica y desacoplada de conseguirlo a través de las implementaciones Context t State. Visita  State Pattern para más detalles.

Visitor

Este patrón se utiliza cuando tenemos que realizar una operación sobre un grupo similar de objects. Con la ayuda del patrón Visitor, podemos mover la lógica operacional desde los objetos a otra clase.

Por ejemplo, pensemos de un carrito de la compra donde podemos añadir distintos tipos de productos (Elements) , cuando clicamos en el botón de comprar,  calcula la cantidad total a ser pagada. Ahora podemos tener la lógica de cálculo en las clases que modelan los productos o podemos mover está lógica a otra clase utilizando el patrón Visitor. Veamos ejemplo en  Visitor Pattern para más detalles de implementación.

Interpreter 

Se utiliza para definir una representación gramátical para un lenguaje y proporciona un interprete para tratar con esta gramática.

El mejor ejemplo de esta patrón es un java compiler que interpreta el código fuente java en byte code entendible por la JVM. Google Translator es también un ejemplo de interprete donde la entrada puede ser en cualquier lenguaje y podemos dar la salida interpretada en otro lenguaje. Visita Interpreter Pattern

Iterator

Es utilizado para proporcionar una forma estandar para recorrer un grupo de objetos. Este patrón se utiliza bastante en las  Java Collection Framework donde el Iterator interfaz proporciona métodos para recorridos a través de una colección.

El patrón Iterator no es sólo sobre recorrer colecciones , podemos proporcionar distintos tipos de iterator basándonos en nuestros requerimientos.El patrón Iterator esconde la implementación actual de recorrido a través de una colección y los programas cliente sólo utilizan los métodos del iterator. Visita Iterator Pattern.

Memento 

Este patrón se utiliza cuando queremos salvar el estado de un objeto de forma que podamos recuperarlo más tarde. Este patrón implementa esta solución de tal forma que el estado grabado del objeto no es accesible fuera del objeto, esto protege la integridad de los datos de estado guardados.

Se implementa con dos objetos –  Originator y Caretaker. Originator es el objeto del cual necesitamos su estado para ser grabado y recuperado y que utiliza una clase inner para guardar el estado de un Object. Esta inner class es llamada Memento y es privada , asi que no puede ser accedida desde otros objetos. Visita Memento Pattern.