본문 바로가기
Java/객체 지향

Enum의 객체 지향적 활용 방법

by 정구정구 2026. 7. 21.

Enum 이란?

  • 서로 관련된 상수들의 집합을 타입으로 정의한 것
  • 단순 static final 상수보다 타입 안정성이 높음 (컴파일 타임에 오타나 잘못된 값을 방지)

작성 예시

public enum ProductStatus{
    FOR_SALE, // 판매 중
    OUT_OF_STOCK, // 품절
    DISCONTINUED, // 단종
    DELETED; // 관리자에 의해 삭제됨
}

 

 

객체 지향적 활용 방법

1. 상태에 따른 판단을 스스로 한다.

안티 패턴

public enum ProductStatus{
    FOR_SALE, // 판매 중
    OUT_OF_STOCK, // 품절
    DISCONTINUED, // 단종
    DELETED; // 관리자에 의해 삭제됨
}
/*주문 재고 차감*/
public void decreaseStockForOrder(int orderQuantity) {
    if (this.status == ProductStatus.DISCONTINUED) {
        throw new IllegalArgumentException("단종된 상품으로 주문할 수 없습니다.");
    }

    if (this.status == ProductStatus.OUT_OF_STOCK || this.stock == 0) {
        throw new IllegalArgumentException("품절된 상품으로 주문할 수 없습니다.");
    }

    if (this.stock < orderQuantity) {
        throw new IllegalArgumentException("상품의 재고가 부족합니다. (현재 재고: " + this.stock + ")");
    }

    int remainingStock = this.stock - orderQuantity;
    this.updateStock(remainingStock);
}

 

상품의 상태에 따라 주문을 막아야하는 경우, Enum 스스로가 이를 판단해서 결과만 넘겨주는 편이 훨씬 좋다.

 

수정된 코드

@Getter
public enum ProductStatus{
    FOR_SALE("판매중"),
    OUT_OF_STOCK("품절"),
    DISCONTINUED("단종됨"),
    DELETED("삭제됨");

    // 에러코드를 위한 상태 String 값 추가
    private final String description;

    ProductStatus(String description) {
        this.description = description;
    }

    // 주문 가능 상태 여부 판단
    public boolean isOrderable(int stock) {

        if (this == DISCONTINUED || (this == OUT_OF_STOCK && stock == 0))
            return false;

        return true;
    }
}
/*주문 재고 차감*/
public void decreaseStockForOrder(int orderQuantity) {
        
    // statuts가 상태에 대한 판단을 담당
    if (!this.status.isOrderable(this.stock)) {
        throw new IllegalArgumentException("상품을 주문할 수 없습니다."
                + "( 상태 :" + this.status.getDescription()
                + " 재고: " + this.stock + " )");
    }

    if (this.stock < orderQuantity) {
        throw new IllegalArgumentException("상품의 재고가 부족합니다. (현재 재고: " + this.stock + ")");
    }

    int remainingStock = this.stock - orderQuantity;
    this.updateStock(remainingStock);
}

 

2. 상태 자신의 다음을 안다.

안티 패턴

public enum OrderStatus {
    PENDING, //준비중
    SHIPPING, //배송중
    COMPLETED, //배송완료
    CANCELED //주문취소
}

 

주문 상태에 대한 enum이 있다. 이 enum은 분명한 단계가 존재한다. 그런 경우, 상태 자신이 다음 상태를 알고 있는 것이 객체 지향적으로 좋은 구조이다.

 

수정된 코드

public enum OrderStatus {
    PENDING {
        @Override public OrderStatus next() { return SHIPPING; }
    },
    SHIPPING {
        @Override public OrderStatus next() { return COMPLETED; }
    },
    COMPLETED {
        @Override public OrderStatus next() {
            throw new IllegalStateException("이미 완료된 주문입니다");
        }
    },
    CANCELLED {
        @Override public OrderStatus next() {
            throw new IllegalStateException("취소된 주문은 진행할 수 없습니다");
        }
    };

    public abstract OrderStatus next();
}
Order order = Order.create(customer, product, 2);
order.advance();   // PENDING → SHIPPING
order.advance();   // SHIPPING → COMPLETED
order.advance();   // IllegalStateException: 안전한 시끄러운 실패

 

 

수정에 대한 장점

1. 상태와 관련된 로직이 한 곳에 응집됨 (응집도 상승)

   - 새로운 상태가 추가되더라도 enum 내부 함수만 수정하면 됨

 

2. if-else 문이 줄어들어 가독성이 좋아짐

 

3. 함수 재사용 가능

'Java > 객체 지향' 카테고리의 다른 글

SOLID 원칙  (0) 2026.07.14
정적 팩토리 메서드  (0) 2026.06.15
상속(Inheritance) VS 합성(Composition)  (0) 2026.06.15
방어적 복사  (0) 2026.06.15
값 객체(Value Object)와 불변성  (0) 2026.06.12