티스토리 뷰

728x90
반응형

자원을 직접 명시하지 말고 의존 객체 주입을 사용하라.


하나의 클래스에서 다른 자원에 의존하는 경우가 많습니다. 또한 해당 클래스가 유틸리티 클래스라면 싱글톤이나 정적 클래스로 사용되는 경우가 많습니다.

 

💡 예제 코드

// 상품 클래스
@Data
public class Product {

    private String name;
    private int price;

    public boolean isPayable(int money) {
        return price <= money;
    }
}

// 할인 정책 클래스
@Data
public class DiscountPolicy {

    private int discountPrice;

    public DiscountPolicy(int discountPrice) {
        this.discountPrice = discountPrice;
    }

    public int discount(int price) {
        if (price < discountPrice) {
            return 0;
        }

        return price - discountPrice;
    }
}

// 상품 구매 결과 응답 DTO 클래스
@Data
public class ShoppingResponse {

    private final Product product;
    private final int price;

    public static ShoppingResponse of(Product product, int price) {
        return new ShoppingResponse(product, price);
    }
}

 

🧨 정적 유틸리티 클래스를 잘못 사용된 예

  • 해당 유틸리티 클래스는 오직 1000원을 할인해주는 할인정책만 적용이 가능합니다. 
  • 유연함과 재사용성이 낮습니다.
public class ShoppingServiceV1 {
    private static final DiscountPolicy discountPolicy = new DiscountPolicy(1000);

    private ShoppingServiceV1() {}

    public static ShoppingResponse buy(Product product, int money) {

        if (!product.isPayable(money)) {
            return null;
        }

        int resultPrice = discountPolicy.discount(product.getPrice());
        return ShoppingResponse.of(product, resultPrice);
    }
}

 

🧨 싱글톤 클래스를 잘못 사용된 예

  • 정적 유틸리티 클래스와 동일하게 싱글톤 클래스 역시 할인정책은 1000원을 할인해주는 고정된 할인정책만 사용 가능합니다.
public class ShoppingServiceV2 {

    private static final DiscountPolicy discountPolicy = new DiscountPolicy(1000);
    private static ShoppingServiceV2 instance = new ShoppingServiceV2();
    
    private ShoppingServiceV2() {}
    
    private static ShoppingServiceV2 getInstance() {
        return instance;
    }

    public ShoppingResponse buy(Product product, int money) {

        if (!product.isPayable(money)) {
            return null;
        }

        int resultPrice = discountPolicy.discount(product.getPrice());
        return ShoppingResponse.of(product, resultPrice);
    }
}

 

결국, 할인정책을 유연하게 변경하면서 쓰기위해서는 정적 클래스가 아닌 인스턴스화가 가능하게 하면서, 할인정책을 인스턴스 생성시 주입받도록 해야합니다. 그렇게 한다면 유연하게 할인정책이 적용 가능합니다.

 

💡 의존 객체 주입(DI)를 사용한 상품 구매 서비스 클래스

  • 할인 정책을 DI를 사용해서 주입받기 때문에 유연하게 할인 정책을 적용할 수 있습니다.
public class ShoppingServiceV3 {

    private final DiscountPolicy discountPolicy;

    public ShoppingServiceV3(DiscountPolicy discountPolicy) {
        this.discountPolicy = discountPolicy;
    }

    public ShoppingResponse buy(Product product, int money) {

        if (!product.isPayable(money)) {
            return null;
        }

        int resultPrice = discountPolicy.discount(product.getPrice());
        return ShoppingResponse.of(product, resultPrice);
    }
}

 

 

 

 

참고자료)

https://catsbi.oopy.io/d7f3a636-b613-453b-91c7-655d71fda2b1

 

728x90
반응형