ModProbe

Javier Alcázar WordPress.com weblog

Archivos de la categoría ‘Java’

Singletons que no son single

Publicado por modprobe en 18Diciembre, 2009

Desde hace un buen rato he sabido que los singletons pueden no ser tan singles usando reflection.

pero ¿cómo es que esto puede suceder?


package single;

import java.lang.reflect.Constructor;

public class Main {

public static void main(String[] args) throws Exception {

Single sin = Single.getInstance();
Single sin2 = Single.getInstance();

if(sin ==sin2){
  System.out.println(" - TEST from singleton equals- ");
}else{
  System.out.println(" - Ouch1  - ");
}

Class<?> forName = Class.forName("single.Single"); //get the class
Constructor<?>[] declaredConstructors = forName.getDeclaredConstructors(); //get constructors fr4om Class
Constructor<?> constructor = declaredConstructors[0]; //get the first constructor (the only one)
constructor.setAccessible(true);//set accesible
Single newInstance = (Single)constructor.newInstance(null);//here we go

if(newInstance == sin){
  System.out.println(" - newInstace and singleton equals - ");
}else{
  System.out.println(" - Singleton is not so single  1 - ");
}

if(newInstance == sin2){
  System.out.println(" - newInstace and singleton2 aARE equals - ");
}else{
  System.out.println(" - Singleton is not so single  22 - ");
}

}

}
package single;

public class Single {

private static final Single instance = new Single();

private Single(){}

public static Single getInstance(){return instance;}

}

El resultado es:

- TEST from singleton equals-
- Singleton is not so single  1 -
- Singleton is not so single  22 -

Una forma más segura de que un singleton sea singleton es usando el approach de enum, Joshua Bloch lo describe en el Item 3 de Effective Java (2nd Edition), el mismo Bloch menciona otro punto en el que hay que tener cuidado: a la hora de deserializar.

Tambien vale la pena revisar revisar el tutorial sobre reflection, viene muy sencillo y preciso:

http://java.sun.com/docs/books/tutorial/reflect/member/index.html

Publicado en Blog, Java | Etiquetado: , , | Deja un Comentario »

Patrones de diseño: Observer

Publicado por modprobe en 3Octubre, 2008

Con este patrón de diseño se puede implementar vista-controlador.

Este patrón de diseño resuelve el problema de actualizar un objeto cuando otro cambie de estado, estos objetos pueden ser componentes dentro de un frame o incluso otros frames.

Existe un observado (extends Observable) y un observador (implements Observer), el observado notifica al observador cuando cambia de estado, y el observador hace lo que crea conveninte con update(Observable obs, Object o).
Hay formas mucho más sencillas de hacer esto, pero aquí hay un ejemplo, el concepto es sencillo.

package voyerismo;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import javax.swing.JComboBox;

/**
 *
 * @author fal
 *
 * Esta clase hereda de Observable, servirá para el primer combobox.
 * Es como un exhibicionista
 *
 */
public class Observado extends Observable{

	private JComboBox jcombobox = null;

	public Observado(){
		String numeros[] = {"-","UNO", "DOS", "TRES","CUATRO"};
		jcombobox = new JComboBox(numeros);

		jcombobox.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				switch(jcombobox.getSelectedIndex() ){
				//En cada case se cambia el estado, y se notifica a los observadores
				case 1:
					setChanged();
					notifyObservers(jcombobox.getSelectedItem() );
					break;
				case 2:
					setChanged();
					notifyObservers(jcombobox.getSelectedItem() );
					break;
				case 3:
					setChanged();
					notifyObservers(jcombobox.getSelectedItem() );
					break;
				case 4:
					setChanged();
					notifyObservers(jcombobox.getSelectedItem() );
					break;
				default:
					setChanged();
					notifyObservers("");
				}

			}

		});

	}

	/**
	 *  Para obtener el combobox
	 * @return combobox El combobox que será espiado
	 */
	public JComboBox getCombobox(){
		return this.jcombobox;
	}

}
package voyerismo;

import java.util.Observable;
import java.util.Observer;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;

/**
 *
 * @author fal
 *
 * Esta clase es la que observa al observado, es como el que estará espiando
 * al combobox de la clase &amp;amp;amp;lt;code&amp;amp;amp;gt;Observado&amp;amp;amp;lt;/code&amp;amp;amp;gt;
 *
 */

public class Observador implements Observer{

	private JComboBox combo = null;
	private DefaultComboBoxModel modeloLight = null;
	private String[] unos = { "Uno", "1", "i", "a", "I" };
	private String[] doses = { "Dos", "2", "ii", "b", "II" };
	private String[] treses = { "Tres", "3", "iii", "c", "III" };
	private String[] cuatros = { "Cuatro", "4", "iv", "d", "IV" };

	public Observador(){
		modeloLight = new DefaultComboBoxModel();
		combo = new JComboBox(modeloLight);
		combo.setEnabled(false);

	}

	/**
	 * Aqui se implementa el método de la interfaz &amp;amp;amp;lt;code&amp;amp;amp;gt;Observer&amp;amp;amp;lt;/code&amp;amp;amp;gt;
	 * el observado le notifica a éste para que éste haga lo tenga que hacer.
	 *
	 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
	 *
	 */
	public void update(Observable observado, Object selectedItem) {
		if(observado != null &amp;amp;amp;amp;&amp;amp;amp;amp; (observado instanceof Observado) ){
			if(selectedItem != null){
			String str = selectedItem.toString();
			if(str.equals("UNO") ){
				enfria(unos);
				combo.setEnabled(true);
			}else if(str.equals("DOS") ){
				enfria(doses);
				combo.setEnabled(true);
			}else if(str.equals("TRES") ){
				enfria(treses);
				combo.setEnabled(true);
			}else if(str.equals("CUATRO") ){
				enfria(cuatros);
				combo.setEnabled(true);
			}else{
				enfria(new String[] {});
				combo.setEnabled(false);
			}
		}

	}

	public JComboBox getCombobox(){
		return this.combo;
	}

	/**
	 * Cambia el modelo(le hace un update)
	 * @param strings
	 */
	private void enfria(String[] strings){
		modeloLight.removeAllElements();
		for (String string : strings) {
			modeloLight.addElement(string);
		}
	}	

}
package voyerismo;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Main {

	public static void main(String args[]) {
		JFrame frame = new JFrame();
		JPanel panel = new JPanel();
		Observado observado = new Observado();
		Observador observador = new Observador();

		//Se agregan los observadores al observado
		observado.addObserver(observador);

		JComboBox combo1 = observado.getCombobox();
		JComboBox combo2 = observador.getCombobox();

		panel.add(new JLabel("Observado") );
		panel.add(combo1);
		panel.add(new JLabel("ObservadoR") );
		panel.add(combo2);

		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		frame.add(panel);
		frame.setTitle("Observado y observador");
		frame.setSize(400, 100);
		frame.setVisible(true);

	}

}

Véase también:

http://en.wikipedia.org/wiki/Observer_pattern
http://www.lcc.uma.es/~pacog/apuntes/poo/Tema4-2.pdf
http://www.patterndepot.com/put/8/observer.pdf
http://java.sun.com/j2se/1.5.0/docs/api/java/util/class-use/Observable.html

Publicado en Blog, Java | Etiquetado: , , , | Deja un Comentario »