Modelo, Vista, Controlador
Modelo, Vista, Controlador
Nivel Básico
18 noviembre, 2014 ◆ 13 comentarios
Conoces los fundamentos de la programación orientada a objetos y has trabajado con bases de
datos. También has implementado interfaces para interactuar con los usuarios de tus aplicaciones.
Pero hasta ahora lo has hecho sin separar metodológicamente cada uno de estos componentes. Si
quieres ir un paso más allá y mejorar en arquitectura software, has llegado al lugar adecuado.
En este ejemplo se tratarán las directrices básicas para afrontar metodología MVC (Modelo – Vista
– Controlador), un modelo maduro que ha demostrado su validez a lo largo de los años en todo tipo
de aplicaciones y sobre multitud de lenguajes y plataformas de desarrollo.
En concreto, en esta guía rápida se empleará como base de datos MySQL y como lenguaje de
programación, Java.
Supuesto Práctico
Se tendrá una base de datos con una tabla donde se almacenará la información de los clientes de
nuestro negocio. Desde una interfaz gráfica, un usuario podrá listar, añadir, modificar o eliminar los
diversos clientes.
La información a almacenar de los clientes será: nombre, apellidos y NIF
Tanto la vista como el controlador estarán implementados en Java mediante Eclipse. Sin embargo,
debido a su simplicidad, el modelo se implementará en MySQL. Se hará uso de procesos
almacenados (stored procedures) en la base de datos.
Debido a que el proyecto Java accederá a una base de datos MySQL, se debe usar un fichero .jar
que se encargará de registrar y emplear el driver adecuado para tal conexión. El fichero se puede
descargar a través del siguiente enlace (en inglés).
Los temas a tratar, son los siguientes:
Una vez abierto Eclipse, se debe acceder a File > New > Java Proyect
En el cuadro de diálogo que aparece, se indica el Project name kadumMVC y se selecciona
JavaSE-1.7 como execution enviroment JRE.
Crear proyecto KadumMVC
Codificación de la clase Bd
La clase Bd se encargará de realizar la conexión a nuestro servidor. Se tendrán dos métodos, el
constructor y un método que devolverá un objeto de la clase Connection. Dicho objeto se empleará
en la clase Controller.
Dentro del proyecto creado, se accede al menú File > New > Class
En el cuadro de diálogo que aparece, tras escribir el nombre de la clase Bd, se pulsa sobre el
botón Finish.
Clase Bd
Se observa que se realizará la conexión a localhost a través del puerto 3306, mediante el usuario
root, el cual no tiene contraseña. En el momento de la creación de un objeto de la clase Bd, se le
indicará el nombre de la base de datos a la que se desea conectar.
Codificación de la clase View
La clase View se encarga de la generación de la interfaz gráfica de la aplicación. La clase View
extenderá la clase JFrame. Para llevar a la creación de los distintos componentes de la interfaz, se
hará uso de la librería javax.swing. La colocación de los componentes se implementará mediante la
clase SpringLayout
El resultado que se obtendrá será la generación de una ventana como la mostrada a continuación,
donde el usuario podrá ver la relación de clientes almacenados en la base de datos. Tendrá la
posibilidad de añadir nuevos clientes o editar o borrar clientes existentes.
Ventana Inicial
Componentes
Los componentes que se emplearán son los mostrados en la imagen siguiente:
Componentes
Todos los componentes irán colocados sobre un objeto JPanel.
Las tres etiquetas se definirán como objetos de la clase JLabel.
Los tres cuadros de texto se definirán como objetos de la clase JTextField.
Los tres botones se definirán como objetos de la clase JButton.
Para la construcción de la tabla, se emplearán varios elementos:
Un objeto JScrollPane.
En el interior del objeto JScrollPane, se colocará un objeto de la clase JTable, el cual
representa la tabla propiamente dicha.
La tabla se construirá a partir de un elemento JDefaultTableModel, el cual unirá la
cabecera de la tabla con el cuerpo de la tabla propiamente dicho.
Para la cabecera de la tabla, se empleará un array de cadenas de caracteres – String[].
Para el cuerpo propiamente dicho, se empleará una matriz de Object – Object[][].
Posiciones de los componentes
Tal y como se ha comentado, las posiciones de los componentes se realizarán mediante la función
putConstraint() de la clase SpringLayout.
Dicha función recibe 5 parámetros:
putConstraint(lado, delComponente, separado, delLado, deOtroComponente)
Los dos primeros parámetros (lado, delComponente) hacen referencia a uno de los 4 lados
de un componente en concreto.
El tercer parámetro (separado) indica la separación en píxeles que se desea tener respecto
a… Es aquí donde entran en función el cuarto y quinto parámetro.
Los dos últimos parámetros (delLado, deOtroComponente), indican respecto a qué lado de
qué componente se desea realizar la separación indicada.
El valor para los parámetros 1 y 4 podrán ser NORTH, SOUTH, EAST, WEST.
El valor para la separación podrá ser positivo o negativo. Cuando el 4 parámetro sea SOUTH o
WEST, en nuestro caso, las cantidades serán negativas, ya que se toma como referencia el
contenedor.
Para más información de la función putConstraint, visitar el enlace siguiente en inglés:
Por simplicidad, todos los componentes se separarán una cantidad de píxeles en función del
contenedor principal.
Posición – JLabels
Se observa la separación de las tres etiquetas respecto al contenedor principal.
Dentro del proyecto creado, se accede al menú File > New > Class
En el cuadro de diálogo que aparece, tras escribir el nombre de la clase View, se
seleccionará la superclass.
Se debe pulsar sobre el botón Browser asociado a Superclass. En el cuadro de diálogo que
aparece, se escribe JFrame y se selecciona la sugerencia aportada por Eclipse.
Por último, se pulsa sobre el botón Finish.
Clave View
El código de la clase será el siguiente. Si se copia el código, se observa que el parámetro de entrada
del método conectaControlador genera un error, ya que la clase Controller aún no está definida.
1 packagekadumMVC;
2
3 importjavax.swing.JFrame;
4 importjavax.swing.JPanel;
5 importjavax.swing.SpringLayout;
6 importjavax.swing.JLabel;
7 importjavax.swing.JTextField;
8 importjavax.swing.JButton;
9 importjavax.swing.JScrollPane;
10 importjavax.swing.table.DefaultTableModel;
11 importjavax.swing.JTable;
12
13 public class View extends JFrame {
14
15 /**************** ATRIBUTOS ***************************/
16 //CONTENEDOR PRINCIPAL
17 Prívate JPanel contenedor;
18
19 //DEFINICIÓN DE LAS ETIQUETAS
20 Prívate JLabel lblNombre;
21 prívate JLabel lblApellido;
22 prívate JLabel lblNIF;
23
24 //DEFINICIÓN DE LOS CUADROS DE TEXTO
25 Protected JTextField txtNombre;
26 Protected JTextField txtApellido;
27 Protected JTextField txtNIF;
28
29 //DEFINICIÓN DE LOS BOTONES
30 Protected JButton btnAdd;
31 Protected JButton btnDel;
32 Protected JButton btnUpd;
33
34 //DEFINICIÓN DE LOS OBJETOS PARA LA TABLA
35 Prívate JScrollPane scroll; //Panel de scroll que contiene
36 la tabla
37 Protected Object[][] datos; //Cuerpo de la tabla
38 Protected String[] cabecera; //Cabecera de la tabla
39 Protected DefaultTableModel dtm;//Unión de la cabecera y la
40 tabla
41 Protected JTable tabla; //Tabla propiamente dicha
42
43 /**************** MÉTODOS ***************************/
//CONSTRUCTOR
44
View(){
45
//Métodos de la JFrame
46
setBounds(100, 100, 450, 300);//Definir las dimensiones
47
de la ventana
48
setTitle("GESTIÓN DE CLIENTES - KADUM"); //Barra de
49
título
50
setDefaultCloseOperation(EXIT_ON_CLOSE); //Acción al
51
pulsar salir
52
53 //CREAR EL CONTENEDOR PRINCIPAL Y AÑADIRLO A LA VENTANA
Se observa que en el constructor, los objetos que se construyen siguen cierto patrón. A modo de
detalle, nos centramos en la construcción del cuadro de texto para el nombre:
1 //CUADRO DE TEXTO PARA EL NOMBRE
2 txtNombre = new JTextField();
3 contenedor.add(txtNombre);
4 sp.putConstraint(SpringLayout.NORTH, txtNombre, 10,
5 SpringLayout.NORTH, contenedor);
6 sp.putConstraint(SpringLayout.WEST, txtNombre, 100,
7 SpringLayout.WEST, contenedor);
8 sp.putConstraint(SpringLayout.EAST, txtNombre, 300,
9 SpringLayout.WEST, contenedor);
Puede resultar curioso que primero se añade al contenedor principal y posteriormente, se posiciona.
Se obtendría el mismo resultado si tras la construcción del objeto, se posicionara y por último, se
añadiera al contenedor.
En el método conectaControlador, se indica que al pulsar los botones se desea que se realice una
acción, que vendrá definida en la clase Controller.
Para que Controller sepa qué botón se ha pulsado, se emplea el método setActionCommand.
INSERTAR
BORRAR
MODIFICAR
Se llamará a un procedimiento almacenado en la base de datos. Se ha decidido implementar el
modelo como procedimientos almacenados en la base de datos.
Para ejecutar los procedimientos almacenados, se empleará la interfaz CallableStatement dentro de
java.sql
Se usará el método prepareCall para invocar a los procedimientos almacenados. Dicho
procedimiento pertenece a la interfaz Connection. Se obtendrá un objeto de dicha interfaz mediante
la invocación al método estático getConexion definido en nuestra clase Bd.
Cada vez que el usuario pulse un botón, se limpiarán los cuadros de texto de la ventana (método
limpia) y se volcarán los datos existentes en la tabla de clientes en el objeto JTable creado en la
clase View (método cargaTabla).
mouseClicked
Este método se ejecutará cuando el usuario pulse sobre una fila de la tabla.
Cuando se pulse sobre una fila, se invocará a un procedimiento almacenado de la base de datos que
obtiene el nombre, apellido y NIF del cliente marcado y cargará los datos en los cuadros de texto de
la ventana.
Para obtener la información devuelta por el procedimiento almacenado, se hará uso de la interfaz
ResultSet.
El resto de métodos cuya definición es obligatoria al implementar la interfaz MouseListener, no
contendrán código alguno.
Código
En el constructor se realizará la vinculación entre el controlador y la ventana. A continuación, se
invocará el método cargaTabla, el cual se encarga de añadir la información de la base de datos a la
ventana.
Se creará la clase Controller:
Dentro del proyecto creado, se accede al menú File > New > Class
En el cuadro de diálogo que aparece, tras escribir el nombre de la clase Controller, se
seleccionarán las interfaces a implementar.
Se debe pulsar sobre el botón Add asociado a Interfaces. En el cuadro de diálogo que
aparece, se buscarán y añadirán ActionListener y MouseListener.
Por último, se pulsa sobre el botón Finish.
Clase Controller
El código de la clase será el siguiente.
1 Package kadumMVC;
2
3 importjava.awt.event.ActionEvent;
4 importjava.awt.event.ActionListener;
5 importjava.awt.event.MouseEvent;
6 importjava.awt.event.MouseListener;
7 importjava.sql.CallableStatement;
8 importjava.sql.ResultSet;
9 importjava.sql.SQLException;
10 importjava.util.Vector;
11
12 public class Controller implements ActionListener,
13 MouseListener {
14 Private View view;
15
16 //CONSTRUCTOR
17 Controller( View view ){
18 this.view = view;
19 cargarTabla();
20 }
21
22 @Override
23 Public void actionPerformed(ActionEvent arg0) {
24 //Objeto para ejecutar los procedimientos almacenados
// en la base de datos
25
26
27 //COMANDO EJECTUADO
28 String comando = arg0.getActionCommand();
29 //Deberá coincidir con alguno de los parámetros
30 // indicados en setActionCommand invocado en la
31 // clase View
32 CallableStatement cs;
33 switch(comando) {
34 case"INSERTAR":
35 try{
36 //Preparar la llamada
cs = Bd.getConexion().prepareCall(
37
"{CALL insertarCliente(?,?,?)}");
38
//Indicar qué información se pasa al
39
// procedimiento
40
cs.setString(1,
41
this.view.txtNombre.getText());
42
cs.setString(2,
43
this.view.txtApellido.getText());
44 cs.setString(3,
45 this.view.txtNIF.getText());
46 //Ejecutar el procedimiento
47 cs.execute();
48 }catch(SQLException e) {
49 System.err.println("Error en la INSERCIÓN");
50 }
51
52 break;
53
Nota: No se ha entrado en detalle en el control de la congruencia de los datos. Por ejemplo, no se
verifica que un cliente ya exista en la base de datos antes de insertarlo. Tampoco se controla la letra
de su NIF.
Dentro del proyecto creado, se accede al menú File > New > Class
En el cuadro de diálogo que aparece, tras escribir el nombre de la clase Principal, se marca
el checkbox correspondiente a public static void main
Por último, se pulsa sobre el botón Finish.
Clase Principal
El código de esta clase es:
1 packagekadumMVC;
2
3 public class Principal {
4 public static void main(String[] args) {
5 //Invocar al constructor de la clase Bd
6 New Bd("kadummvc");
7 //Crear un objeto de la clase View
8 View vista = new View();
9 //Crear un objeto de la clase Controller
10 Controller controlador = new Controller(vista);
11 //Vincular la vista y el controlador
12 vista.conectaControlador(controlador);
13
14 }
15 }
Como nota, observar que se realiza la vinculación entre la clase Controller y View en dos sentidos.
Se crea la base de datos kadummvc. Como se observa, es el mismo nombre que recibe como
parámetro de entrada la invocación al constructor Bd en la clase Principal.
Se crea la tabla cliente. Con los campos id, nombre, apellido y NIF
CREATETABLE`cliente` (
1
`id` int(10) NOT NULL
2
AUTO_INCREMENT,
3 `nombre` varchar(50) DEFAULTNULL,
4 `apellido` varchar(50) DEFAULTNULL,
5 `nif` varchar(10) DEFAULTNULL,
6 PRIMARYKEY(`id`)
7 );
Relación de ficheros
Base de Datos
Se debe acceder en Eclipse a la clase Principal que contiene la función main y ejecutarla,
pulsando la tecla F11.
Se mostrará un mensaje en la consola indicando que se ha conectado a la base de datos
kadummvc, tal y como se especificó en la creación del objeto bd dentro de la clase Principal.
Y aparecerá la ventana en las coordenadas 100, 100 con un tamaño de 450×300 tal y como
se especificó en el constructor de la clase View.
Ejecución
Añadir clientes
Se rellenan los campos de texto.
Rellenar campos
Se pulsa Añadir.
Se añadirá la información a la base de datos, se limpiarán los campos de texto y se reflejará
en la tabla el cliente insertado.
Insertado
Modificar clientes
Para modificar un cliente, se pulsa sobre la fila del registro a modificar. De esa forma, se
cargan los datos para ese cliente.
Se reescribe la información correctamente y se pulsa sobre Editar.
Seleccionar y editar
Borrado
Creación de un ejecutable
Una vez comprobada que la aplicación funciona según lo previsto, se lleva a cabo la construcción
del fichero ejecutable en Eclipse.
Tras pulsar Next, se mostrará un cuadro de diálogo donde se configura qué clase es la que
contiene el método main que interesa ejecutar. Dónde se desea almacenar el ejecutable y la
opción de incluir las bibliotecas necesarias en el fichero ejecutable.