반응형
Recent Posts
Recent Comments
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

Bbaktaeho

[Java] Builder pattern (빌더 패턴, 점층적 생성자 패턴, 자바빈 패턴) 본문

프로그래밍 (Programming)/자바 (Java)

[Java] Builder pattern (빌더 패턴, 점층적 생성자 패턴, 자바빈 패턴)

Bbaktaeho 2020. 9. 21. 18:10
반응형

인스턴스화 (Instantiate)


클래스를 인스턴스화(객체 생성)할 때 생성자를 통해서 하게 됩니다.

하지만 생성자로 생성하는데 어려움이 있을 수 있습니다.

 

자동차 클래스를 예시로 보여드리겠습니다.

class Car {
    private String brand;
    private String engine;
    private String name;
    private String tire;
    private int capacity;
    private int price;

    Car(String brand, String engine, String name, String tire, int capacity, int price) {
        this.brand = brand;
        this.engine = engine;
        this.name = name;
        this.tire = tire;
        this.capacity = capacity;
        this.price = price;
    }
}

Car 클래스의 생성자를 보면 많은 인자를 받아옵니다. 때문에 어떠한 인자 값이 어떤 값을 나타내는지 확인하기 어렵습니다. 또한 몇 개의 값만 주면 되는 상황에선 특정 파라미터의 인자 값으로 null을 전달해야 합니다.

이러한 상황은 가독성이 매우 떨어진다는 것을 알 수 있습니다.

 

Car myCar = new Car("현대", "독일엔진", "제네시스", "한국타이어", 4, 700000000);

위의 코드는 생성자를 사용해서 인스턴스화 합니다.

만약에 몇 가지 인자만 아는 경우에 객체를 생성해야 한다면 null 또는 0을 전달해야 합니다.

 

Car myCar = new Car("현대", null, "제네시스", null, 0, 0);

생성자에 전달하는 인자 값이 어떠한 값을 나타내는지 알기 어렵기 때문에 가독성이 좋지 않습니다.

 

이를 해결하기 위해 생성자 오버 로딩을 통해서 여러 개의 생성자를 구현해야 합니다.

점층적 생성자 패턴 (Telescoping Constructor Pattern)


생성자 오버 로딩을 통해서 객체를 생성할 때 가독성을 높입니다.

 

위의 Car 클래스의 생성자를 오버 로딩해보겠습니다.

 

    Car() {
        this("", "", "", "", 0, 0);
    }

    Car(String brand) {
        this(brand, "", "", "", 0, 0);
    }

    Car(String brand, String engine) {
        this(brand, engine, "", "", 0, 0);
    }

    Car(String brand, String engine, String name) {
        this(brand, engine, name, "", 0, 0);
    }

    Car(String brand, String engine, String name, String tire) {
        this(brand, engine, name, tire, 0, 0);
    }

    Car(String brand, String engine, String name, String tire, int capacity) {
        this(brand, engine, name, tire, capacity, 0);
    }

    Car(String brand, String engine, String name, String tire, int capacity, int price) {
        this.brand = brand;
        this.engine = engine;
        this.name = name;
        this.tire = tire;
        this.capacity = capacity;
        this.price = price;
    }

인스턴스화 측면에선 가독성이 조금이라도 좋아질 순 있어도 클래스는 그렇지 않습니다.

 

setter 메서드를 이용해서 클래스를 깔끔하게 구현할 수 있습니다.

자바 빈 패턴 (JavaBeens Pattern)


객체를 생성하고 나서 늦게 멤버 변수를 초기화시킵니다.

생성자의 영향을 받지 않기 때문에 생성자를 많이 구현할 필요가 없습니다.

 

setter 메서드를 만들어보겠습니다.

public void setBrand(String brand) {
    this.brand = brand;
}

public void setEngine(String engine) {
    this.engine = engine;
}

public void setName(String name) {
    this.name = name;
}

public void setTire(String tire) {
    this.tire = tire;
}

public void setCapacity(int capacity) {
    this.capacity = capacity;
}

public void setPrice(int price) {
    this.price = price;
}

intellij IDEA는 alt + insert 키를 누르면 자동으로 만들 수 있습니다.

 

Car myCar = new Car();
myCar.setBrand("기아");
myCar.setName("카니발");

객체의 public 메서드를 통해서 멤버 변수를 초기화하는데 이러한 방법은 한 번의 생성자 호출로 생성을 끝낼 수 없으므로 일관성이 깨지고, 변하지 않은 immutable 객체를 만들 수 없습니다.

빌더 패턴


점층적 생성자 패턴과 자바 빈 패턴의 장점을 결합한 것이 빌더 패턴

asfirstalways.tistory.com/350

새로운 객체가 필요한 곳에서 직접 생성하기 전에 필수 인자 값들을 전달하여 빌더 객체를 만든 후 빌더 객체에 정의된 메서드를 호출해서 객체를 생성하는 것입니다.

 

빌더 패턴을 사용해보겠습니다.

class Car {
    private String brand;
    private String engine;
    private String name;
    private String tire;
    private int capacity;
    private int price;

    Car(Builder builder) {
        this.brand = builder.brand;
        this.engine = builder.engine;
        this.name = builder.name;
        this.tire = builder.tire;
        this.capacity = builder.capacity;
        this.price = builder.price;

    }

    public static class Builder {
        private String brand;
        private String engine;
        private String name;
        private String tire;
        private int capacity;
        private int price;

        // 필수적인 필드 : brand
        public Builder(String brand) {
            this.brand = brand;
        }

        public Builder engine(String engine) {
            this.engine = engine;
            return this;
        }

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

        public Builder tire(String tire) {
            this.tire = tire;
            return this;
        }

        public Builder capacity(int capacity) {
            this.capacity = capacity;
            return this;
        }

        public Builder price(int price) {
            this.price = price;
            return this;
        }

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


}

Car 클래스 안에 정적 클래스인 Builder를 만들어줍니다.

Builder 클래스는 build 메서드를 통해서 새로운 Car 객체를 생성합니다. 

 

Car myCar = new Car.Builder("현대")
                .engine("독일엔진")
                .name("제네시스")
                .tire("한국타이어")
                .capacity(4)
                .price(70000000)
                .build();

참고 자료


asfirstalways.tistory.com/350

 

[DP] 2. 빌더 패턴(Builder Pattern)

#2. 빌더 패턴(Builder pattern) 인스턴스를 생성할 때, 생성자(Constructor)만을 통해서 생성하는데는 어려움이 있다. 빌더 패턴은 이 문제를 기반으로 고안된 패턴 중 하나이다. 예를 들면, 생성자 인자�

asfirstalways.tistory.com

 

반응형