[java] Java에서 많은 매개 변수를 사용하여 생성자 관리

일부 프로젝트에는 체인을 따라 내려갈 때 더 많은 매개 변수를 추가하는 클래스 계층 구조가 있습니다. 맨 아래에서 일부 클래스는 최대 30 개의 매개 변수를 가질 수 있으며이 중 28 개는 수퍼 생성자로 전달됩니다.

나는 Guice와 같은 것을 통해 자동화 된 DI를 사용하는 것이 좋을 것임을 인정할 것입니다. 그러나 몇 가지 기술적 이유 때문에 이러한 특정 프로젝트는 Java로 제한됩니다.

유형에 따라 인수를 알파벳순으로 구성하는 규칙은 작동하지 않습니다. 유형이 리팩토링되면 (인수 2로 전달한 원이 이제 Shape가 됨) 갑자기 순서가 잘못 될 수 있기 때문입니다.

이 질문은 구체적이고 “그게 당신의 문제라면, 당신은 디자인 수준에서 잘못하고있다”는 비판으로 가득 차있을 수 있지만, 저는 단지 어떤 관점을 찾고 있습니다.



답변

빌더 디자인 패턴이 도움이 될 수 있습니다. 다음 예를 고려하십시오.

public class StudentBuilder
{
    private String _name;
    private int _age = 14;      // this has a default
    private String _motto = ""; // most students don't have one

    public StudentBuilder() { }

    public Student buildStudent()
    {
        return new Student(_name, _age, _motto);
    }

    public StudentBuilder name(String _name)
    {
        this._name = _name;
        return this;
    }

    public StudentBuilder age(int _age)
    {
        this._age = _age;
        return this;
    }

    public StudentBuilder motto(String _motto)
    {
        this._motto = _motto;
        return this;
    }
}

이렇게하면 다음과 같은 코드를 작성할 수 있습니다.

Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
                 .name("Spicoli")
                 .age(16)
                 .motto("Aloha, Mr Hand")
                 .buildStudent();

필수 필드를 생략하면 (아마 이름이 필요함) Student 생성자가 예외를 throw하도록 할 수 있습니다. 그리고 어떤 종류의 인수 순서를 추적 할 필요없이 기본 / 선택 인수를 가질 수 있습니다. 이러한 호출의 순서가 동일하게 잘 작동하기 때문입니다.


답변

객체 내부에 관련 매개 변수를 캡슐화 할 수 있습니까?

예 : 매개 변수가 다음과 같은 경우


MyClass(String house, String street, String town, String postcode, String country, int foo, double bar) {
  super(String house, String street, String town, String postcode, String country);
  this.foo = foo;
  this.bar = bar;

대신 다음을 가질 수 있습니다.


MyClass(Address homeAddress, int foo, double bar) {
  super(homeAddress);
  this.foo = foo;
  this.bar = bar;
}


답변

아마도 당신이하고 싶은 것은 Builder 클래스가있는 것입니다. 그런 다음 다음과 같이 할 수 있습니다.

MyObject obj = new MyObjectBuilder().setXxx(myXxx)
                                    .setYyy(myYyy)
                                    .setZzz(myZzz)
                                    // ... etc.
                                    .build();

8 페이지 와이 Josh Bloch 프레젠테이션 (PDF) 또는 이 효과적인 Java 리뷰를 참조하십시오.


답변

글쎄, 빌더 패턴을 사용하는 것이 하나의 해결책 이 될 수 있습니다 .

하지만 20 ~ 30 개의 매개 변수에 도달하면 매개 변수간에 높은 관계가 있다고 생각합니다. 따라서 (제안 된대로) 논리적으로 정상적인 데이터 개체로 래핑하는 것이 가장 합리적 일 것입니다. 이러한 방식으로 데이터 개체는 매개 변수 간의 제약 조건의 유효성을 이미 확인할 수 있습니다.

과거의 모든 프로젝트에 대해 너무 많은 매개 변수 (28 개가 아니라 8 개였습니다!)가 너무 많아서 더 나은 데이터 모델을 만들어 코드를 정리할 수있었습니다.


답변

Java 1.4로 제한되어 있으므로 DI를 원한다면 Spring 은 매우 적절한 옵션이 될 것입니다. DI는 생성자 매개 변수가 서비스이거나 런타임 중에 변하지 않는 부분에서만 유용합니다.

객체를 생성하는 방법에 대한 변수 옵션을 원한다는 사실로 인해 이러한 모든 생성자가 있다면 Builder 패턴 사용을 진지하게 고려해야합니다.


답변

가장 좋은 해결책은 생성자에 너무 많은 매개 변수가없는 것입니다. 생성자에서 실제로 필요한 매개 변수 만 객체를 올바르게 초기화하는 데 필요한 매개 변수입니다. 여러 매개 변수가있는 생성자를 가질 수 있지만 최소 매개 변수 만있는 생성자를 가질 수도 있습니다. 추가 생성자는이 간단한 생성자를 호출하고 그 후에 다른 매개 변수를 설정하기 위해 setter를 호출합니다. 이렇게하면 점점 더 많은 매개 변수를 사용하여 체인 문제를 피할 수있을뿐만 아니라 편의 생성자를 가질 수도 있습니다.


답변

나는 정말로 사용을 추천 할 수있다 빌더 패턴을 사용할 때 Immutables 또는 POJOBuilder 를 사용하는 .