최근 빌더 패턴이 매우 강한 상황이되었지만 서브 클래스 할 필요가있었습니다. 일부 솔루션을 찾아 보았고 몇 가지 제네릭을 제안했지만 다른 것은 일반적인 서브 클래 싱을 제안했습니다. 그러나 내가 본 예제 중 아무 것도 필드는 객체 작성을 시작하기 위해 필드가 필요했습니다. 내가 갇혀있는 곳을 설명하기 위해 작은 예제를 썼다. 매 회마다 잘못된 클래스를 반환하고 정적 메서드를 재정의 할 수 없으며 super()가 잘못된 데이터 형식을 반환하는 등 문제가있는 벽으로 계속 실행했습니다. 과도한 사용 이외의 방법은 없습니다. 제네릭 중.하위 분류 및 필수 매개 변수가있는 빌더 디자인 패턴?
이 상황에서 올바른 방법은 무엇입니까?
테스터
import person.Person;
import person.Student;
public class Tester
{
public static void main(String[] args)
{
Person p = Person.builder("Jake", 18).interest("Soccer").build();
// Student s = Student.builder(name, age) <-- It's weird that we still have access to pointless static method
// Student s = Student.builder("Johnny", 24, "Harvard", 3).address("199 Harvard Lane") <-- returns Person builder, not student
Student s = ((Student.Builder)Student.builder("Jack", 19, "NYU", 1).address("Dormitory")).build(); // really bad
}
}
사람 클래스
package person;
import java.util.ArrayList;
import java.util.List;
public class Person
{
// Required
protected String name;
protected int age;
// Optional
protected List<String> interests = new ArrayList<>();
protected String address = "";
protected Person(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
public List<String> getInterests() { return interests; }
public String getAddress() { return address; }
// person.person does not allow builder construction
// unless all required fields are provided
/* Problem: I have to repeat the constructor fields here, very annoying */
public static Builder builder(String name, int age)
{
Person p = new Person(name, age);
return new Builder(p);
}
public static class Builder
{
Person reference;
protected Builder(Person reference)
{
this.reference = reference;
}
public Builder address(String address)
{
reference.address = address;
return this;
}
public Builder interest(String interest)
{
reference.interests.add(interest);
return this;
}
public Person build()
{
return reference;
}
}
}
학생 클래스
package person;
import java.util.ArrayList;
import java.util.List;
public class Student extends Person
{
// Required
protected String school;
protected int year;
// Optional
protected List<String> subjects = new ArrayList<>();
// This looks good
public Student(final String name, final int age, final String school, final int year)
{
super(name, age);
this.school = school;
this.year = year;
}
public String getSchool() { return school; }
public int getYear() { return year; }
public List<String> getSubjects() { return subjects; }
/* Here's where my issues are:
* Override doesn't compile on static methods but how else can I describe that I want to
* override this functionality from the Person class?
*
* Extending 'Person' does not enforce that I need to provide 'name', 'age', etc like it would
* if this was a normal design pattern using the 'new' keyword. I have to manually drag fields
* from 'person' and place them here. This would get VERY messy with an additional class
*
* User can STILL call the Person builder on a Student object, which makes no sense. */
/*@Override*/ public static Builder builder(String name, int age, String school, int year)
{
Student s = new Student(name, age, school, year);
return new Builder(s);
}
public static class Builder extends Person.Builder
{
// Student reference; <--- this should not be needed since we already
// have a variable for this purpose from 'Person.Builder'
public Builder(final Student reference)
{
super(reference);
}
/* Things begins to get very messy here */
public Builder subject(String subject)
{
((Student)reference).subjects.add(subject);
// I guess I could replace the reference with a student one, but
// I feel like that infringes on calling super() builder since we do the work twice.
return this;
}
@Override public Student build()
{
// I can either cast here or
// rewrite 'return reference' every time.
// Seems to infringe a bit on subclassing.
return (Student)super.build();
}
}
}
는 [빌더가 중첩 될 필요는 없다] 일부 코드 (https://stackoverflow.com/questions/19130876/builder-pattern-inside-vs- 외부 클래스), 반환 할 구현을 표시하는 컨텍스트가 필요합니다. 기본 클래스의 생성자는 유지하지만'setSchool()','setYear()'또는'addSubject()'가 호출되면 Person 대신 Student를 반환합니다. –
빌더 패턴의 값 중 하나는 많은 생성자 매개 변수로 끝나지 않는다는 것입니다. – DwB