1 개요
빌더 패턴(Builder Pattern)은 주로 "복잡한 개체를 단계별로 구축"하는 데 사용됩니다. 여기서 "단계별"은 안정적인 알고리즘인 반면 복잡한 개체의 다양한 부분은 자주 변경됩니다. 따라서 빌더 패턴은 주로 "객체 부분"의 변화하는 요구 사항을 해결하는 데 사용됩니다. 이를 통해 객체 생성 프로세스를 보다 세밀하게 제어할 수 있습니다.
예시 2개
휴대폰 생산을 예로 들면, 각 휴대폰은 화면, CPU, 배터리로 구분됩니다. 이제 생산되는 휴대폰에는 Apple과 Samsung 두 가지 유형이 있습니다.
사과:
다음과 같이 코드 코드를 복사합니다.
패키지 org.scott.builder.before.use;
import java.util.ArrayList;
java.util.List 가져오기;
/**
* @author 스캇
* @버전 2013-11-20
* @설명
*/
공개 클래스 ApplePhone {
List<String> 부분 = new ArrayList<String>();
공공 무효 createCPU() {
parts.add("컵: 퀄컴");
}
공공 무효 createScreen() {
parts.add("화면: JDI");
}
공공 무효 createBattery() {
parts.add("배터리: DeSai");
}
공개 무효 쇼(){
System.out.print("제품 구성요소 정보:");
for(문자열 부분 : 부분){
System.out.print(part + "/t");
}
}
}
삼성:
다음과 같이 코드 코드를 복사합니다.
패키지 org.scott.builder.before.use;
import java.util.ArrayList;
java.util.List 가져오기;
/**
* @author 스캇
* @버전 2013-11-20
* @설명
*/
공개 클래스 SamsungPhone {
List<String> 부분 = new ArrayList<String>();
공공 무효 createCPU() {
parts.add("컵: MTK");
}
공공 무효 createScreen() {
parts.add("화면: 삼성");
}
공공 무효 createBattery() {
parts.add("배터리: DeSai");
}
공개 무효 쇼(){
System.out.print("제품 구성요소 정보:");
for(문자열 부분 : 부분){
System.out.print(part + "/t");
}
}
}
테스트 클라이언트:
다음과 같이 코드 코드를 복사합니다.
패키지 org.scott.builder.before.use;
/**
* @author 스캇
* @버전 2013-11-20
* @설명
*/
공개 클래스 BuilderTest {
개인 정적 ApplePhone iphone = new ApplePhone();
개인 정적 SamsungPhone samPhone = new SamsungPhone();
공개 정적 무효 메인(문자열 인수[]){
iphone.createCPU();
iphone.createScreen();
iphone.createBattery();
iphone.show();
samPhone.createCPU();
samPhone.createScreen();
samPhone.createBattery();
samPhone.show();
}
}
문제를 발견하셨나요? 즉, 휴대폰을 생산하는 모든 공정은 동일하지만, 공정 명칭은 동일하지만, 구체적인 공정은 몇 가지만 다를 뿐입니다. 각 프로세스 변경 사항을 처리하고, 이 중에서 "모든 변경 사항에 대응하기 위해 변경되지 않은" 것을 추출하고 변경 사항을 특정 제품에 넘길 수 있습니다.
구체적으로 어떻게 해야 할까요? 이번에는 빌더 모드가 유용합니다.
먼저 전화 인터페이스를 살펴보겠습니다.
다음과 같이 코드 코드를 복사합니다.
패키지 org.scott.builder.after.use;
import java.util.ArrayList;
java.util.List 가져오기;
/**
* @author 스캇
* @버전 2013-11-20
* @설명
*/
공개 추상 클래스 전화 {
protected List<String> 부분 = new ArrayList<String>();
public void add(문자열 부분){
부품.추가(부분);
}
공개 무효 쇼(){
System.out.print("제품 구성요소 정보:");
for(문자열 부분 : 부분){
System.out.print(part + "/t");
}
}
}
Apple 휴대폰 카테고리:
다음과 같이 코드 코드를 복사합니다.
패키지 org.scott.builder.after.use;
/**
* @author 스캇
* @버전 2013-11-20
* @설명
*/
공개 클래스 ApplePhone은 Phone을 확장합니다.{
}
삼성 휴대폰 카테고리:
다음과 같이 코드 코드를 복사합니다.
패키지 org.scott.builder.after.use;
/**
* @author 스캇
* @버전 2013-11-20
* @설명
*/
공개 클래스 SamsungPhone은 Phone을 확장합니다.{
}
그런 다음 생산 단계에 대한 인터페이스 빌더를 정의합니다.
다음과 같이 코드 코드를 복사합니다.
패키지 org.scott.builder.after.use;
/**
* @author 스캇
* @버전 2013-11-20
* @설명
*/
공용 인터페이스 빌더 {
공공 무효 buildCPU();
공공 무효 buildScreen();
공공 무효 buildBattery();
공중전화 getPhone();
}
iPhone용 빌더:
다음과 같이 코드 코드를 복사합니다.
패키지 org.scott.builder.after.use;
/**
* @author 스캇
* @버전 2013-11-20
* @설명
*/
공개 클래스 ApplePhoneBuilder는 Builder를 구현합니다.{
개인 전화 전화 = new ApplePhone();
@보수
공공 무효 buildCPU() {
phone.add("컵: 퀄컴");
}
@보수
공공 무효 buildScreen() {
phone.add("화면:JDI");
}
@보수
공공 무효 buildBattery() {
phone.add("배터리: DeSai");
}
@보수
공용 전화 getPhone() {
반납 전화;
}
}
삼성 휴대폰용 빌더:
다음과 같이 코드 코드를 복사합니다.
패키지 org.scott.builder.after.use;
/**
* @author 스캇
* @버전 2013-11-20
* @설명
*/
공개 클래스 SamsungPhoneBuilder가 Builder를 구현합니다.{
개인 전화 전화 = 새로운 SamsungPhone();
@보수
공공 무효 buildCPU() {
phone.add("컵:MTK");
}
@보수
공공 무효 buildScreen() {
phone.add("화면:삼성");
}
@보수
공공 무효 buildBattery() {
phone.add("배터리: DeSai");
}
@보수
공용 전화 getPhone() {
반납 전화;
}
}
휴대폰의 특정 생산을 지도하는 이사:
다음과 같이 코드 코드를 복사합니다.
패키지 org.scott.builder.after.use;
/**
* @author 스캇
* @버전 2013-11-20
* @설명
*/
공개 수업 감독 {
개인 빌더 빌더;
퍼블릭 디렉터(빌더 빌더){
this.builder = 빌더;
}
공개 무효 구성(){
builder.buildCPU();
builder.buildScreen();
builder.buildBattery();
}
}
마지막으로 테스트 클래스를 작성합니다.
다음과 같이 코드 코드를 복사합니다.
패키지 org.scott.builder.after.use;
/**
* @author 스캇
* @버전 2013-11-20
* @설명
*/
공개 클래스 BuilderTest {
개인 정적 빌더 iPhoneBuilder = new ApplePhoneBuilder();
개인 정적 빌더 samPhoneBuilder = new SamsungPhoneBuilder();
공개 정적 무효 메인(String[] args) {
디렉터 디렉터 = 새 디렉터(iPhoneBuilder);
Director.construct();
전화번호 = iPhoneBuilder.getPhone();
System.out.println("아이폰");
전화.쇼();
감독 = 새 감독(samPhoneBuilder);
Director.construct();
전화 = samPhoneBuilder.getPhone();
System.out.println("/nsamSung");
전화.쇼();
}
}
실행 결과:
다음과 같이 코드 코드를 복사합니다.
아이폰
제품 부품 정보: CUP: Qualcomm SCREEN: JDI BATTERY: DeSai
삼성
제품 부품 정보: 컵: MTK 스크린: 삼성 배터리: DeSai
여기서 두 개의 Phone 엔터티 클래스는 비어 있습니다. 이 경우 생략할 수 있습니다. Phone 인터페이스도 생략할 수 있는 경우 Director, Builder 및 특정 Builder 구현 클래스만 남습니다. 또한 ApplePhone 클래스와 SamsungPhone 클래스는 서로 다른 휴대폰 브랜드이므로 서로 관련이 없는 클래스가 두 개 이상 발생하는 경우에는 공용 인터페이스인 Phone이 존재할 필요가 없습니다. , 그렇다면 Builder 인터페이스에 지정된 getPhone() 메소드의 반환 값을 결정하는 방법은 무엇입니까?
반환 값 유형이 ApplePhone이든 SamsungPhone이든 관계없이 반환되는 결과의 유형이 일정하지 않기 때문에 문제가 발생합니다. 이때 Phone은 빈 인터페이스(어떤 메소드도 포함하지 않는 인터페이스)로 정의한 다음, 서로 관계가 없는 특정 제품 클래스가 이 인터페이스를 구현하도록 할 수 있습니다. 그런 다음 getPhone(의 반환 값 유형을 구현합니다. ) Builder 인터페이스에 지정된 메서드는 여전히 Phone 유형이므로 문제가 해결됩니다. 하지만 이 경우에는 빌더 모드를 사용할 필요가 없습니다.