빌더 패턴

ynkim·2024년 11월 14일
0

빌더 패턴

복잡한 객체들을 단계별로 생성할 수 있도록 하는 생성 디자인 패턴

구조

  • 빌더 인터페이스: 공통적인 제품 생성 단계들을 선언
  • 구상 빌더: 각 단계별로 구현을 제공
  • 제품: 결과로 나온 객체. 다른 빌더에 의해 생성된 제품들은 같은 클래스 계층구조 혹은 인터페이스에 속할 필요가 없다.
  • 디렉터: 생성 단계를 호출하는 순서를 정의

예시 코드

class Computer {
    private String CPU;
    private String RAM;
    private int storage;
    private boolean hasGraphicsCard;
    private boolean hasCoolingSystem;

    public void setCPU(String CPU) {
        this.CPU = CPU;
    }

    public void setRAM(String RAM) {
        this.RAM = RAM;
    }

    public void setStorage(int storage) {
        this.storage = storage;
    }

    public void setGraphicsCard(boolean hasGraphicsCard) {
        this.hasGraphicsCard = hasGraphicsCard;
    }

    public void setCoolingSystem(boolean hasCoolingSystem) {
        this.hasCoolingSystem = hasCoolingSystem;
    }
}

class ComputerManual {
    private String manualContent;

    public void addContent(String content) {
        this.manualContent = (this.manualContent == null ? "" : this.manualContent + "\n") + content;
    }

    @Override
    public String toString() {
        return "Computer Manual:\n" + manualContent;
    }
}

// Builder 인터페이스
interface ComputerBuilder {
	void reset();
    void buildCPU();
    void buildRAM();
    void buildStorage();
    void buildGraphicsCard();
    void buildCoolingSystem();
}

// 구상 Builder 클래스
class ComputerConcreteBuilder implements ComputerBuilder {
    private Computer computer;

    public ComputerConcreteBuilder() {
        this.computer = new Computer();
    }
    
    @Override
    public void reset() {
        this.computer = new Computer();
    }

    @Override
    public void buildCPU(String cpu) {
        computer.setCPU(cpu);
    }

    @Override
    public void buildRAM(String ram) {
        computer.setRAM(ram);
    }

    @Override
    public void buildStorage(int storage) {
        computer.setStorage(storage);
    }

    @Override
    public void buildGraphicsCard(boolean hasGraphicsCard) {
        computer.setGraphicsCard(hasGraphicsCard);
    }

    @Override
    public void buildCoolingSystem(boolean hasCoolingSystem) {
        computer.setCoolingSystem(hasCoolingSystem);
    }

    public Computer getComputer() {
        return this.computer;
    }
}

class ComputerManualBuilder implements ComputerBuilder {
    private ComputerManual manual;

    public ComputerManualBuilder() {
        this.manual = new ComputerManual();
    }
    
    @Override
    public void reset() {
        this.manual = new ComputerManual();
    }

    @Override
    public void buildCPU(String cpu) {
        manual.addContent("CPU: " + cpu + " installed.");
    }

    @Override
    public void buildRAM(String ram) {
        manual.addContent("RAM: " +  ram + " is installed.");
    }

    @Override
    public void buildStorage(int storage) {
        manual.addContent("Storage: " + storage + "GB default storage.");
    }

    @Override
    public void buildGraphicsCard(boolean hasGraphicsCard) {
    	if (hasGraphicsCard) {
        	manual.addContent("Graphics Card: Included.");
        } else {
        	manual.addContent("Graphics Card: Not included.");
        }
    }

    @Override
    public void buildCoolingSystem(boolean hasCoolingSystem) {
    	if (hasCoolingSystem) {
        	manual.addContent("Cooling System: Included.");
        } else {
        	manual.addContent("Cooling System: Not included.");
        }
    }

    public ComputerManual getManual() {
        return this.manual;
    }
}

// Director 클래스
class Director {
    private ComputerBuilder builder;

    public Director(ComputerBuilder builder) {
        this.builder = builder;
    }

    public void constructGamingComputer() {
        builder.reset();
        builder.buildCPU("Intel i9);
        builder.buildRAM("32GB");
        builder.buildStorage(1024);
        builder.buildGraphicsCard(true);
        builder.buildCoolingSystem(true);
    }

    public void constructServerComputer() {
        builder.reset();
        builder.buildCPU("AMD EPYC");
        builder.buildRAM("64GB");
        builder.buildStorage(4096);
        // Server에서는 Graphics Card는 포함하지 않지만 Cooling System은 포함
        builder.buildCoolingSystem(true);
    }
}

// 클라이언트 코드
public class Main {
    public static void main(String[] args) {
        // Gaming Computer 생성
        ComputerConcreteBuilder computerBuilder = new ComputerConcreteBuilder();
        Director director = new Director(new ComputerConcreteBuilder());
        director.constructGamingComputer();
        Computer gamingComputer = computerBuilder.getComputer();

        // Server Computer 생성
        director.constructServerComputer();
        Computer serverComputer = computerBuilder.getComputer();

        // Gaming Computer Manual 생성
        ComputerManualBuilder manualBuilder = new ComputerManualBuilder();
        director = new Director(manualBuilder);
        director.constructGamingComputer();
        ComputerManual gamingManual = manualBuilder.getManual();

        // Server Computer Manual 생성
        director.constructServerComputer();
        ComputerManual serverManual = manualBuilder.getManual();
    }
}

장단점

장점

  • 객체를 단계별로 생성할 수 있다.
  • 같은 생성 코드를 재사용할 수 있다.
  • 비즈니스 로직에서 생성 코드를 분리하여 단일 책임 원칙을 지킨다.
    단점
  • 클래스의 수가 늘어난다.

0개의 댓글