2010-05-24 8 views
10

Tengo una interfaz ProductService con el método findByCriteria. Este método tenía una larga lista de parámetros que aceptan nulos, como productName, maxCost, minCost, producer y así sucesivamente.¿Hay algo malo en declarar la clase anidada dentro de la interfaz en java?

I refactorizado este método mediante la introducción de Parameter Object. He creado la clase SearchCriteria y ahora firma del método se ve así:

findByCriteria (SearchCriteria criteria) 

pensé que los casos de SearchCriteria solamente son creados por personas que llaman método y sólo se utilizan en el interior findByCriteria método, es decir:

void processRequest() { 
    SearchCriteria criteria = new SearchCriteria() 
            .withMaxCost (maxCost) 
            ....... 
            .withProducer (producer); 

    List<Product> products = productService.findByCriteria (criteria); 
    .... 
} 

y

List<Product> findByCriteria(SearchCriteria criteria) { 
    return doSmthAndReturnResult(criteria.getMaxCost(), criteria.getProducer());  
} 

Así que no quería crear una clase pública separada para SearchCriteria y ponerla dentro de ProductServiceInterface:

public interface ProductService { 
    List<Product> findByCriteria (SearchCriteria criteria); 

    static class SearchCriteria { 
     ... 
    } 
} 

¿Hay algo mal con esta interfaz? ¿Dónde colocarías la clase SearchCriteria?

+3

No es necesario marcar SearchCriteria como estático, todos los tipos de miembros de las interfaces son implícitamente estáticos (y públicos). – Oak

Respuesta

3

Creo que se ve bien. Señala claramente que el SearchCriteria está destinado para su uso con ProductService s específicamente.

Algunas personas, sin embargo, argumentan que las clases anidadas parecen un poco extrañas y afirman que esto sería un diseño excesivo y que el alcance del paquete es lo suficientemente bueno en la mayoría de los casos, incluido esto.

2

no es malo, y puede ser útil si se desea una agrupación más estrecha entre las interfaces y algunos objetos de utilidad, como comparadores. (He hecho exactamente lo mismo con una interfaz, y las clases internas proporcionan comparadores útiles que comparan instancias de la interfaz.)

puede ser un poco incómodo para los clientes utilizar, ya que deben anteponer el nombre de clase interno con el nombre de la interfaz (o use una importación estática), pero un IDE bueno se encarga de esto (pero el código puede verse salpicado de declaraciones Interface.SomeClass, que no se ven tan bien)

Sin embargo, en el caso, SearchCriteria no se ve tan bien acoplado a la interfaz, por lo que puede ser más útil como una clase de paquete regular.

2

les animo a utilizar las clases cuando se tiene métodos que pueden requerir más o menos anulables argumentos; que le da la capacidad de proporcionar todo lo que necesita sin tener que llamar a un método como:

someMethod("foo", null, null, null, null, null, null, ..., "bar"); 

El uso de tales MECANISMO, la llamada al método sería algo así como:

someMethod(new ObjParam().setFoo("foo").setBar("bar")); 

El segundo método es prescindible y reutilizable (sin toneladas de métodos anulados). ¡Y no estoy diciendo que la anulación de método sea mala! Todo lo contrario. Sin embargo, con muchos argumentos opcionales, preferiría la segunda llamada.

En cuanto a las clases internas, que son útiles a veces, pero yo personalmente las siguientes pautas:

  1. intenta utilizar las clases internas sólo cuando la clase interna debe ser privada (por ejemplo: en el caso de una costumbre Implementación LinkedList, la clase Node es una clase privada y por lo tanto es una clase interna.
  2. generalmente solo si la clase no es reutilizable y se usa principalmente dentro de un (muy) pequeño grupo de clases que lo convertiré en una clase interna
  3. El "padre" y la clase interna se vuelven lo suficientemente grandes; a continuación, ambas clases reciben su propio archivo fuente de Java para la legibilidad, a menos que la clase interna deba ser privada como para el primer punto.

Tenga en cuenta que, la clase interna o no, el compilador Java se crear un .class para cada clase. Cuanto más los use, menos legible será su código. Es decisión suya decidir si están justificados o no ...

0

Me temo que me gustaría votar por lo malo. Bastante mal de todos modos, puedes hacer cosas peores ...

Para simplificar, una clase debe tener solo una responsabilidad. Su implementación de ProductService tiene una definición de clase de criterio dentro, así que cuando pasea por el código, debe saber en qué parte del archivo se encuentra.

Más importante aún, la separación hace que el código de las entidades involucradas sea más simple y más explícito. Para mí, esto anula todas las demás preocupaciones (ah, aparte de que el código es correcto, por supuesto). Encuentro simplicidad & explictness son más útiles cuando se trata de retener mi cabello, o al menos el de las personas que mantendrán las cosas ...

+0

No hay una definición de clase de criterio dentro de la clase ProductServiceImpl. Está definido dentro de la interfaz ProductService. – Roman

+0

Hmm, supongo que leí más de las respuestas sobre el problema de las clases internas que su código original. Su clase de criterio está en la firma de servicio público, por lo que la llena un cliente. La mayoría de las personas que conozco escribiría esto como una clase pública regular; después de todo, tiene un uso público. – StripLight

Cuestiones relacionadas