티스토리 뷰

자바에서 객체를 생성하는 3가지 방법에 대해 알아보겠습니다.

 

1. 생성자

스타벅스 음료 3잔을 자바 코드로 만들어보겠습니다.

StarbucksDrink라는 클래스를 만들고 음료의 종류마다 값을 받을 수 있도록 생성자를 만들었습니다. 총 4개의 생성자를 통해 다양한 음료를 만들 수 있는 구조네요.

public class ConstructorClass {
    public static void main(String[] args) {
        StarbucksDrink drink1 = new StarbucksDrink(2, true); //투샷, 아이스
        StarbucksDrink drink2 = new StarbucksDrink(2, 2, true); //투샷, 시럽2번, 아이스
        StarbucksDrink drink3 = new StarbucksDrink(true, true, true); //아이스초코 + 휘핑
    }
}

class StarbucksDrink {

    private int shot = 0;
    private boolean isIce = false;
    private int syrup = 0;
    private int caramel = 0;
    private int vanilla = 0;
    private boolean isWhipping = false;
    private boolean isChoco = false;

    public StarbucksDrink(int shot, boolean isIce) {
        this.shot = shot;
        this.isIce = isIce;
    }
    public StarbucksDrink(int shot, int syrup, boolean isIce) {
        this.shot = shot;
        this.syrup = syrup;
        this.isIce = isIce;
    }
    public StarbucksDrink(int syrup, int vanilla, boolean isIce) {
        this.syrup = syrup;
        this.vanilla = vanilla;
        this.isIce = isIce;
    }
    public StarbucksDrink(int shot, boolean isChoco, boolean isWhipping, boolean isIce) {
        this.shot = shot;
        this.isChoco = isChoco;
        this.isWhipping = isWhipping;
        this.isIce = isIce;
    }
}

하지만 이런 형태는 음료의 갯수마다 생성자를 만들어줘야 되고
 StarbucksDrink drink1 = new StarbucksDrink(2, true); //투샷, 아이스
 StarbucksDrink drink2 = new StarbucksDrink(2, 2, true); //투샷, 시럽2번, 아이스
 StarbucksDrink drink3 = new StarbucksDrink(true, true, true); //아이스초코 + 휘핑

이렇게 주석이 달려있지 않으면 어떤 음료를 만드는지 코드로는 확인이 힘들어 보이네요. 그럼 조금 더 코드의 가독성을 높히는 방법을 알아봅시다.

 

2. SetterGetter

이번엔 생성자는 없고 (생성자를 코드에 명시하지 않으면 기본 생성자가 호출됩니다) getter setter 메서드들이 생겼습니다.

각 멤버 변수마다 getter와 setter를 통해서 값을 넣고 불러올 수 있는 구조입니다.

public class SetterGetterClass {

    public static void main(String[] args) {

        StarbucksDrinkSetterGetter drink1 = new StarbucksDrinkSetterGetter();
        drink1.setShot(2);
        drink1.setIce(true);

        StarbucksDrinkSetterGetter drink2 = new StarbucksDrinkSetterGetter();
        drink2.setShot(2);
        drink2.setSyrup(2);
        drink2.setIce(true);

        StarbucksDrinkSetterGetter drink3 = new StarbucksDrinkSetterGetter();
        drink3.setIce(true);
        drink3.setChoco(true);
        drink3.setWhipping(true);
    }

}

class StarbucksDrinkSetterGetter {

    private int shot;
    private boolean isIce;
    private int syrup;
    private int caramel;
    private int vanilla;
    private boolean isWhipping;
    private boolean isChoco;

    public int getShot() {
        return shot;
    }

    public void setShot(int shot) {
        this.shot = shot;
    }

    public boolean isIce() {
        return isIce;
    }

    public void setIce(boolean ice) {
        isIce = ice;
    }

    public int getSyrup() {
        return syrup;
    }

    public void setSyrup(int syrup) {
        this.syrup = syrup;
    }

    public int getCaramel() {
        return caramel;
    }

    public void setCaramel(int caramel) {
        this.caramel = caramel;
    }

    public int getVanilla() {
        return vanilla;
    }

    public void setVanilla(int vanilla) {
        this.vanilla = vanilla;
    }

    public boolean isWhipping() {
        return isWhipping;
    }

    public void setWhipping(boolean whipping) {
        isWhipping = whipping;
    }

    public boolean isChoco() {
        return isChoco;
    }

    public void setChoco(boolean choco) {
        isChoco = choco;
    }
}

위의 생성자 방법보단 어떤 음료를 만드는지 좀 더 명확하게 보여지네요.

하지만 코드가 길어지는 단점과 더 큰 문제는 값의 변경이 자유롭다는 겁니다.

예를들어 코드를 잘못 짜면

 

StarbucksDrinkSetterGetter drink1 = new StarbucksDrinkSetterGetter();
drink1.setShot(2);
drink1.setIce(true);

StarbucksDrinkSetterGetter drink2 = new StarbucksDrinkSetterGetter();
drink2.setShot(2);
drink1.setSyrup(2);
drink2.setIce(true);

 

굵게 적힌 부분처럼 값이 잘못들어갈 수 있게 됩니다. 

그럼 이런 음료를 만드는 클래스에 쓸 수 있는 더 좋은 방법을 알아봅시다.

 

3. Builder

이번엔 빌더에 대해 알아봅시다.

StarbucksDrink클래스는 좀 더 복잡하게 생겼네요.

멤머변수들은 final 선언이 되어서 한 번 값이 들어가게 되면 변경이 불가능하죠.

위의 값이 잘못들어가는 것에 대한 대응이 될 수 있겠네요.

public class BuilderClass {

    public static void main(String[] args) {
        StarbucksDrinkBuilder drink1 = new StarbucksDrinkBuilder.Builder().shot(2).isIce(true).build();
        StarbucksDrinkBuilder drink2 = new StarbucksDrinkBuilder.Builder().shot(2).syrup(2).isIce(true).build();
        StarbucksDrinkBuilder drink3 = new StarbucksDrinkBuilder.Builder().isChoco(true).isWhipping(true).isIce(true).build();
    }
}
class StarbucksDrinkBuilder {

    private final int shot;
    private final int syrup;
    private final int caramel;
    private final int vanilla;
    private final boolean isWhipping;
    private final boolean isChoco;
    private final boolean isIce;

    public static class Builder {
        private int shot;
        private int syrup;
        private int caramel;
        private int vanilla;
        private boolean isWhipping;
        private boolean isChoco;
        private boolean isIce;

        public Builder shot(int value) {
            shot = value;
            return this;
        }
        public Builder isIce(boolean value) {
            isIce = value;
            return this;
        }
        public Builder syrup(int value) {
            syrup = value;
            return this;
        }
        public Builder caramel(int value) {
            caramel = value;
            return this;
        }
        public Builder vanilla(int value) {
            vanilla = value;
            return this;
        }
        public Builder isWhipping(boolean value) {
            isWhipping = value;
            return this;
        }
        public Builder isChoco(boolean value) {
            isChoco = value;
            return this;
        }
        public StarbucksDrinkBuilder build() {
            return new StarbucksDrinkBuilder(this);
        }
    }
    private StarbucksDrinkBuilder(Builder builder) {
        shot = builder.shot;
        syrup = builder.syrup;
        caramel = builder.caramel;
        vanilla = builder.vanilla;
        isWhipping = builder.isWhipping;
        isChoco = builder.isChoco;
        isIce = builder.isIce;
    }
}

SetterGetter와 달리 초기화 할 때 한 줄에 바로 값이 초기화가 되었네요.

생성자 방법과도 다르게 어떤 음료를 만드는지 코드로 명확하게 보이기도 하구요.

 

그렇다고 무조건 Builder 방식이 좋은건 아니에요. 값의 변경이 자유로운 경우에는 SetterGetter방식을,

생성 방식이 1가지만 있다면 복잡한 코드보다는 간단히 생성자를 만드는것도 좋겠죠.

 

파라미터 갯수가 적을 때는 Builder클래스를 구성하는 시간보단 생성자처럼 만드는게 더 빠른 개발 속도를 낼 수 있지만 서비스 개발을 하다보면 시간이 지날 수록 파라미터가 많아지고 복잡해지기 때문에 초기에 Builder나 SetterGetter 형태로 구성해놓으면 개발 비용이 점점 줄어드는 효과를 볼 수 있어요.

'개발 > Java' 카테고리의 다른 글

Effective Java 3/E - 싱글턴을 만드는 방법  (0) 2021.01.16
Effective Java 3/E - 정적 팩터리 메서드  (0) 2021.01.14
자바 스트림 -2  (0) 2021.01.01
자바 스트림 -1  (0) 2020.12.26
자바 람다식  (0) 2020.12.19
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   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
글 보관함