Mejor diseño para implementacion en Java.

Iniciado por SDCC, 17 Abril 2019, 07:42 AM

0 Miembros y 1 Visitante están viendo este tema.

SDCC

Hola a todos tengo un problema un tanto sencillo pero que no sè cual de mis ideas sea las mas adecuada.

El problema se reduce a una parte en donde debo tener 2 tipos de directorios.

  • Directorio Empresarial.Almacenada contactos empresariales
  • Directorio Personal.Almacena contactos personales

Practicamente ambos directorios deben realizar los mismos mètodos solo con la diferencia de el tipo de contacto que almacena y algunas consultas que se realizan dentro de los métodos..
Nota.Existe una superclase que es padrede "Contacto Empresarial" y "Contacto Personal" que lleva como nombre "Contacto"

Mi primera solución planteaba crear una interfaz "Directorio" como la siguiente(hacen falta definir un par de metodos).

Pero no sé si esta esta es la manera más correcta de hacerlo, es decir, los argumentos y retornos de los métodos ya estan definidos en la la interfaz lo cual en cierta manera me hace pensar en como tratar los casos especiales de cada clase que lo implemente, es decir, en mi clase "Directorio Empresarial" yo quiero que sus metodos solo acepten como argumentos y constructor datos de tipo "Contacto Empresarial" pero al yo implementar una interfaz esta me esta definiendo argumentos como de tipo "Contacto" que podria provocar errores en algunos metodos por lo cual entonces seria necesario lanzar una exepcion si me envian como argumento un objeto de tipo "Contacto"en vez de uno de tipo "Contacto Empresarial" .... y en ese caso me hace pensar que tal vez mi diseño es erroneo o que no sè como diseñar este tipo de problemas.

Yo necesito definir estos dos tipos de directorios por que aunque realmente tiene los mismos mètodos yo requiero que algunos mètodos hagan la misma tarea pero ademas hagan una consulta especifica a una base de datos en el caso de que sea un directorio empresarial/personal va ser distinta la consulta.

Tengo idea de un segundo planteamiento donde defino una clase abstracta "Directorio " que tiene como atributo un objeto de tipo "Contacto" y los respectivos metodos y que las clases derivadas ("Directorio Empresarial" y "Directorio Personal") solo implementa esos metodos pero caigo en la misma duda. Un Directorio Empresarial al heredar de Directorio va tener como atributo un objeto Contacto que puede almacenar por herencia un Contacto Empresarial pero ¿ Yo debo exigir que a esta clase Directorio Personal solo se le pueda pasar objetos Contacto Empresarial aún cuando los métodos que hereda y sobrescribe de la clase Directorio permiten que se la pase un objeto de Contacto?. Yo podría pasar por alto esto debido a que estoy haciendo el programa y sé como puedo controlar que esta clase de error no suceda pero me da la sensación de que como buena practica las clases no se deben prestar para dejar huecos que puedan causar errores al ser reutilizadas.

rub'n

#1
Tal cual tus dos afirmaciónes son válidas
 
No hay una clave para crear una herencia perfecta.

Con el uso de super y override puedes hacer lo que estás pidiendo tranquilamente.

Eso de que si te devuelve un objeto de tipo contacto o contactoEmpresarial , puedes comprobarlo por ti mismo tranquilamente, simple y tan llanamente probando

Si tienes un método en tu interface, clase abstract base, o clase, ejemplo, getConexion, las clases que implementa a ese método , es decir que hereden a una de esas clases, tanto por simple herencia, o herencia múltiple, tendrán su propia  implementación y conectarán  a la tabla, o procedimiento almacenado correspondiente, claro está que cada implementación debe apuntar a la tabla correcta.

No te vuelvas loco enredándote, que lo que quieres hacer si que se puede.

Las 2 maneras son validas

* Eso de la interface que te vuelve objetos de tipo contacto en ves de empresarial? Es Bull shit o algo parecido

Tu clase Contacto, debería ser más bien la clase abstracta base de la cual van a heredar las clases hijas, Contacto Empresarial y otros tipos de contactos y ya. No te vuelvas loco, y esa clase abstracta puede a la vez, implementar una interface, que contenga los métodos que quieres que implementen a las clases hijas de diferentes tipos de contactos, o la misma clase abstracta dar implementacion a ellos y las hijas usarlos con dicha implementacion, empresarial,personal, u otros dog.

Añadiendo Generics se puede ahorrar mas código,  pero ahí se complica solo un poco más eso es todo.pero ni tanto, y sobre los Generics hace poco implemente algo parecido, y totalmente funcional, vía herencia múltiple usando una interface de servicio genérico para un log de una db.

Código (java) [Seleccionar]
public interface ServicioXXX<T extends ServicioBean>

y ese servicio dentro retorna parámetros genéricos tipo T , en cada método. Al heredar de ahí, osea  

Código (java) [Seleccionar]
public class ServicioXXXImpl implements ServicioXXX<ServicioBean>

ese parámetro específico dentro del operador diamante indica lo que retornará cada método en ServicioXXXImpl o parámetros en dichos métodos, teniendo un solo servicio, ahorrando tener múltiples ServixioXXXA, ServicioXXXB, y casting innecesarios en la mayoría de los casos.



rubn0x52.com KNOWLEDGE  SHOULD BE FREE!!!
If you don't have time to read, you don't have the time (or the tools) to write, Simple as that. Stephen

SDCC

Pero por ejemplo en cada método que yo implemente de la interfaz deberia hacer una comprobación de si es de tipo "Contacto Empresarial" o "Contacto Personal" y en caso contrario lanzar una excepcion como IlegalArgumentException? , ¿ Es normal que en estos casos se llene de casteos y de lanzamiento de excepciones para especificar que no se aceptan argumentos de la clase base si no de solo una clase especifica? o se hace la clase sin tomar en cuenta esas cosas pensando en que el programa jamas le va pasar como argumento un objeto de la herencia que no era para ese tipo de directorio.

rub'n

#3
Cita de: SDCC en 17 Abril 2019, 16:36 PM
Pero por ejemplo en cada método que yo implemente de la interfaz deberia hacer una comprobación de si es de tipo "Contacto Empresarial" o "Contacto Personal" y en caso contrario lanzar una excepcion como IlegalArgumentException? , ¿ Es normal que en estos casos se llene de casteos y de lanzamiento de excepciones para especificar que no se aceptan argumentos de la clase base si no de solo una clase especifica? o se hace la clase sin tomar en cuenta esas cosas pensando en que el programa jamas le va pasar como argumento un objeto de la herencia que no era para ese tipo de directorio.


:xD has un código ya, y ponlo aquí, y veremos qué hacemos dog, creo que te estás rompiendo el coco tú solo dog, pero tranquilo como decía el popular Jack el destripator, empecemos por peñascos.

El operador instanceof te puedo ayudar para comprobar tipos en runtime, si es que te entiendo, otra cosa es tu posible código.


rubn0x52.com KNOWLEDGE  SHOULD BE FREE!!!
If you don't have time to read, you don't have the time (or the tools) to write, Simple as that. Stephen

SDCC

#4
Interfaz.
Código (java) [Seleccionar]

import java.util.Vector;

public interface Directorio {
   public boolean eliminarContacto(Contacto c);
   public boolean agregarContacto(Contacto c)throws IllegalArgumentException;
   public boolean modificarContacto(int id,Contacto c)throws IllegalArgumentException;
   public Vector<Contacto> getContactos();
}



Clase Directorio Personal.
Código (java) [Seleccionar]

import java.util.Iterator;
import java.util.Vector;

public class DirectorioPersonal implements Directorio {
   
   Vector<ContactoPersonal> contactos;
   
   public DirectorioPersonal(){
       contactos = new Vector<>();
   }
   
   @Override
   public boolean eliminarContacto(Contacto c){
       /*Hace polimorfismo con el metodo equals . No hay problema */
       
       return contactos.remove(c);
   }
   
   @Override  
   public boolean agregarContacto(Contacto c)throws IllegalArgumentException{
       if(!(c instanceof ContactoPersonal))
           throw new IllegalArgumentException();
        return contactos.add((ContactoPersonal)c);
   }
   
   
   
   @Override
   public Vector<Contacto> getContactos(){
       Vector<Contacto> lista = new Vector<>();
       Iterator itr1 = contactos.iterator();
       while(itr1.hasNext()){
           lista.add((Contacto)itr1.next());
       }
       return lista;
   }
   
   @Override
   public boolean modificarContacto(int id,Contacto c)throws IllegalArgumentException{
       if(!(c instanceof ContactoPersonal))
           throw new IllegalArgumentException();
       
       Contacto contacto = getContacto(id);
       if( contacto == null)
            return false;
//Polimorfismo en metodo swap
       contacto.swap(c);
       return true;
   }
   
/*Metodo auxiliar para modificar contacto */
   private Contacto getContacto(int id){
       Iterator itr = contactos.iterator();
       ContactoPersonal aux = null;
       
       while(itr.hasNext()){
           aux = (ContactoPersonal)itr.next();
           if(aux.getId() == id)
               return aux;
       }
       
       return null;
   }
}


rub'n

Eso es todo el código? No uses Vector es Bull sh$t, mejor List<E>


rubn0x52.com KNOWLEDGE  SHOULD BE FREE!!!
If you don't have time to read, you don't have the time (or the tools) to write, Simple as that. Stephen

SDCC

#6
En su mayoria si, solo me falta agregar algunas cosas sobre la base de datos pero seria solo agregar llamados a metodos dentro de esas clases "Directorios". Estaba pensando usar el patron de diseño DAO y DTO que hasta donde he visto es practicamente hacer una clase DAO por cada clase DTO que sea la que haga las consultas relacionadas con esa clase a la base de datos.

Esta solo es una parte del problema principal pero el otro segmento del problema ya lo tengo diseñado y en su mayoría ya esta pasado a código.

CalgaryCorpus

Sugiero usar HashMap, se eliminan los ciclos que tienes en los metodos modificarContacto y getContacto
Aqui mi perfil en LinkedIn, invitame un cafe aqui