2010-11-25 15 views
5

Tengo una clase pública, que necesita 7 parámetros para pasar. Por el momento, puedo hacer que 3 de ellos pasen al constructor y otros 4 a un método público en la clase. De esta manera:Manejo de más de 7 Parámetros

 

Public Class AClass{ 
    private XClass axClass; 
    private String par4; 
    private String par5; 
    private String par6; 
    private String par7; 

    public AClass(String par1, String par2, String par3){ 
     aXClass = new XClass(par1,par2,par3); 
    } 

    public execute(String par4,String par5, String par6, String par7){ 
     //this is needed because they are used in other private methods in this class 
     this.par4 = par4; 
     this.par5 = par5; 
     this.par6 = par6; 
     this.par7 = par7; 

     //call other private methods within this class. 
     //about 7 lines here 
    } 

} 

 

Mi pregunta es, ¿es este el camino correcto para preguntar cliente de la clase a la que pasa en parametros?

+0

Creo que lo que debe pasar al constructor depende de la situación. ¿Puede explicar en detalle qué AClass y XClass hacen y cuáles son estos 7 parámetros? – Emil

+1

"Si tiene un procedimiento con diez parámetros, probablemente se haya perdido alguno". -Alan Perlis :-) – missingfaktor

Respuesta

9

No debe haber nada que le impida pasar 7 parámetros a un constructor, si eso es lo que desea. No sé si hay una cantidad máxima de parámetros que se pueden pasar a un método en Java, pero ciertamente es mayor que 7 si hay un máximo.

Cuando crea una clase y sus métodos públicos, está creando una interfaz sobre cómo usar y acceder a esa clase. Entonces, técnicamente, lo que has hecho hasta ahora es correcto. ¿Es la "forma correcta" de pedir al cliente de una clase que transmita argumentos? Depende de usted, el diseñador de la interfaz.

Mi primer instinto cuando vi que se pasaban 7 parámetros fue preguntar silenciosamente "¿Existe alguna relación entre algunos o todos estos parámetros que podría significar que se combinarían bien en una clase propia?" Eso podría ser algo a lo que te refieres cuando miras tu código. Pero esa es una cuestión de diseño, no de corrección.

+0

Buena respuesta. No hay un "camino correcto", no hay una elección claramente superior. Tienes que usar tu mejor juicio. –

+0

Como todos los 7 parámetros son cadenas, si están todos en constructor, ¿no confundirá a las personas? Si creo un objeto de datos ficticio que solo tiene setter y getter para los 7 parámetros, el cliente debe saber acerca de este tipo de datos, ¿es el enfoque correcto solo para este propósito? – sarahTheButterFly

+0

Oh, definitivamente, podría confundir a la gente.Pero eso es un problema de diseño en comparación con uno técnico. Es por eso que sugerí que miraras cuáles son esos parámetros y veas si hay alguna manera de encapsularlos en otra clase. Por ejemplo, tal vez los siete son jugadores en algún equipo. Entonces puede encontrar que tiene más sentido crear una clase de Equipo con una lista de nombres de jugadores dentro de ella, y luego pasar una instancia de Equipo en lugar de varias cadenas de nombres de jugador. – Marvo

1

¿No puedes simplemente hacer una clase/hashmap que almacena estos parámetros y pasarlos a la función?

public excute(Storageclass storageClass){ 
     //this is needed because they are used in other private methods in this class 
     this.par4 = storageClass.getPar4(); 
     this.par5 = storageClass.getPar5(); 
     this.par6 = storageClass.getPar6(); 
     this.par7 = storageClass.getPar7(); 

     //or 
     this.storageClass = storageClass; 
    } 
+0

También hay algunas discusiones aquí de las expresiones idiomáticas de "Parámetros nombrados" en Java: http://stackoverflow.com/questions/1988016/named-parameter-idiom-in-java – HostileFork

1

Realmente no veo el problema con eso.

En cualquier caso, se puede crear un objeto "Solicitud" o algo similar:

class SomeClass { 
    private String a; 
    private String b; 
    .... 
    public SomeClass(Request r) { 
     this.a = r.get("a"); 
     this.b = r.get("b"); 
     ... 
    } 

    public void execute(Request other) { 
     this.d = other.get("d"); 
     this.e = other.get("d"); 
     ... 
    } 
} 

Ver también: http://c2.com/cgi/wiki?TooManyParameters

1

Sin conocer el uso de la clase hija, puedo decir que hay nada intrínsecamente incorrecto con lo que has hecho.

Nota sin embargo que usted tiene que declarar

private XClass axClass;

en las variables de su AClass.

Sin embargo, dices 'Puedo hacer ...' ¿Esto significa que hay algún problema al declararlo de otra manera?

+0

Gracias Kevin por notar eso. Lo he editado. No hay problema con declararlos todos en el constructor. Lo que quise decir fue que logré dividirlos en 3 y 4. – sarahTheButterFly

1

No me importa mucho, porque un objeto debe estar 100% listo para ser utilizado después de que se llame a su constructor. No es como está escrito en tu ejemplo.

Si los parámetros pasados ​​al método de ejecución pueden simplemente consumirse, y ese es el método de interés para los clientes, no veo ninguna razón para que sean miembros de datos en la clase.

Sin saber más acerca de sus objetivos finales, es difícil de decir. Pero volvería a pensar en esta implementación.

+0

¡Hola, duffymo! Lo siento, solo quiero saludarte. Probablemente no sea apropiado :) – sarahTheButterFly

+0

Perfectamente bien, Sarah. Si estás en Estados Unidos, espero que tengas unas buenas vacaciones mañana. – duffymo

+0

jeje. No estoy en América Pero gracias de todos modos. Y también es mañana aquí - Australia. disfruta de tus vacaciones :) – sarahTheButterFly

1

Si usted está pensando en introducir una AClass.someMethod() que necesita saber par4-7 sin necesidad de AClass.excute() han llamado, entonces es claro que debe estar pasando los parámetros en el constructor.

Por otro lado: si se puede construir una instancia de este objeto, con sólo par1-3 y hacer algo significativo con ella además llamada excute() entonces tiene sentido para permitir que el objeto que se construye con menos de los siete parámetros completos .

Sin embargo, mi propia estética es tratar de limitar el número de "modos" que puede tener un objeto en el que ciertos métodos funcionan y otros fallan. Entonces, idealmente, un objeto completamente construido está listo para ejecutar cualquier método que el programador pueda llamar. Me preocuparía más el tema del diseño que preocuparme demasiado por la cantidad de parámetros para el constructor.

Pero, como han señalado otros, a veces existe una agrupación natural de estos parámetros que pueden merecer sus propios objetos. Por ejemplo: en muchas API en lugar de pasar (x, y, ancho, alto) por todos lados, usan objetos rectangulares.

+0

También: ¿tu ortografía es http://en.wiktionary.org/wiki/execute intencional o no? Por lo general, simplemente asumiría que el error tipográfico no vale la pena mencionarlo, pero acabo de ver hace un minuto un método llamado subGridRowColapsed que lo convirtió en la API jqGrid ... tengo que verificarlo dos veces. http://www.trirand.com/jqgridwiki/doku.php?id=wiki:subgrid&s[]=expand – HostileFork

+0

Lo siento, es involuntario. Error de tipografía. : P – sarahTheButterFly

1

Como ya escribieron otros, es técnicamente correcto pasar 7 parámetros, aunque no muy 'fácil de usar', si puede decirlo.

Como no escribió mucho sobre esta clase, puedo sugerir una pequeña cosa: en el constructor solo está creando el objeto XClass, por lo que sería sensato crear este objeto antes y pasarlo como un parámetro único.

Algo como esto:

... 
XClass aXClass = new XClass(par1, par2, par3); 
AClass aClass = new AClass(aXClass); 
... 

Y este es el constructor:

public AClass(XClass aXClass) { 
     this.aXClass = aXClass; 
} 
6

me gustaría ir para el Builder Pattern en lugar de muchos parámetros del constructor según lo sugerido por

Effective Java Elemento 2: Considera un constructor cuando te enfrentas a muchos constructores Héctor parámetros

Aquí es una clase simple para ilustrar:

public class Dummy { 

    private final String foo; 
    private final String bar; 
    private final boolean baz; 
    private final int  phleem; 

    protected Dummy(final Builder builder) { 
     this.foo = builder.foo; 
     this.bar = builder.bar; 
     this.baz = builder.baz; 
     this.phleem = builder.phleem; 
    } 

    public String getBar() { 
     return this.bar; 
    } 

    public String getFoo() { 
     return this.foo; 
    } 

    public int getPhleem() { 
     return this.phleem; 
    } 

    public boolean isBaz() { 
     return this.baz; 
    } 

    public static class Builder { 
     private String foo; 
     private String bar; 
     private boolean baz; 
     private int  phleem; 

     public Dummy build() { 
      return new Dummy(this); 
     } 

     public Builder withBar(final String bar) { 
      this.bar = bar; 
      return this; 
     } 

     public Builder withBaz(final boolean baz) { 
      this.baz = baz; 
      return this; 
     } 

     public Builder withFoo(final String foo) { 
      this.foo = foo; 
      return this; 
     } 

     public Builder withPhleem(final int phleem) { 
      this.phleem = phleem; 
      return this; 
     } 

    } 

} 

Usted podría crear una instancia de esta manera:

Dummy dummy = new Dummy.Builder() 
        .withFoo("abc") 
        .withBar("def") 
        .withBaz(true) 
        .withPhleem(123) 
        .build(); 

La parte buena: se obtiene todos los beneficios de parámetros del constructor (p.ej inmutabilidad si lo deseas), pero también obtienes código legible.

+0

+1, repito esta respuesta. – missingfaktor

+1

Debe agregar un control en el método build() para validar todos los parámetros "obligatorios" que se establecieron, para ser estrictamente equivalentes a un constructor con 7 parámetros (es decir: hacer una diferencia entre una configuración de usuario "nula" y el valor predeterminado "nulo"). Esa es la desventaja de esta solución. – naab

+1

@naab en estos días, utilizaría el https://immutables.github.io/ framework para generar los constructores. Agrega esta funcionalidad fuera de la caja, por defecto –

Cuestiones relacionadas