java-squid / effective-java

effective java 3e study
105 stars 38 forks source link

[아이템 64] 객체는 인터페이스를 사용하라 #66

Closed kses1010 closed 3 years ago

102092 commented 3 years ago
tmdgusya commented 3 years ago

저도 이거 보면서 DI 만 생각났네요.. 근데 확실히 인터페이스를 잘 쓰면 프로그램이 상당히 유연해지고, 코드를 짜는 습관에도 도움이 많이 되더라고요. 먼져 추상화 시키려하는 습관들이 생겨서

ghojeong commented 3 years ago

제가 Spring 을 전혀 몰라서, 덕분에 올려주신 링크 읽어보면서 공부를 할 수 있었는데,

"객체는 인터페이스를 사용해라" 에서 DI 가 떠오르신 이유가 무엇인지 좀더 설명해주실 수 있으신가요?

보니깐 ApplicationContext 에서 xml 에 정의된 내용에 따라, 클래스의 인터페이스로 선언된 객체에게 실제 클래스를 "Injecting" 하는 내용 같은데, DI 를 하기 위해서는 인터페이스를 사용해야하기에 떠오르셨던건가요?

대화 흐름을 못따라가서 여쭈어봅니다.

kses1010 commented 3 years ago

토비의 스프링, 김영한님의 스프링 강의를 수강하면서 정리한 내용입니다.

제어의 역전 (IoC: Inversion of Control)

프레임워크 vs 라이브러리

의존관계 주입(DI: Dependency Injection)

정적인 클래스 의존 관계

import 코드만 보고 의존관계를 쉽게 판단할 수 있다.

→ 정적인 의존관계는 애플리케이션을 실행하지 않아도 분석할 수 있다. image


public class AppConfig {

    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

    private MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

    public OrderService orderService() {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }
    // 고정 할인 정책
    public DiscountPolicy discountPolicy() {
        return new FixDiscountPolicy();
    }
}

// OrderServiceImpl.class
public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
}

이제 여기서 OrderSeviceImpl에서 고정 할인 정책이 아닌 할인율 정책으로 변경할 경우

public DiscountPolicy discountPolicy() {
//        return new FixDiscountPolicy();
        return new RateDiscountPolicy();
}

로만 바꾸면 됩니다. 서비스 로직인 OrderServiceImpl에서 바꿀 필요가 없겠죠? 이건 자바로직이고 여기서 만약 스프링으로 전환한다면

@Configuration
public class AppConfig {

    @Bean
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

    @Bean
    public OrderService orderService() {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

    @Bean
    public DiscountPolicy discountPolicy() {
//        return new FixDiscountPolicy();
        return new RateDiscountPolicy();
    }
}

로 애너테이션으로 등록이 가능합니다. 김영한님 강의에서는 xml에서 애너테이션으로 바꾸는 추세라고 하셨고, xml을 쓴다고 하면 아마 레거시쪽이 많이 쓸 듯하네요. IoC는 제어의 역전이며, DI는 스프링 프레임워크에서 지원하는 IoC의 형태라고 생각하시면 됩니다. 자세한건 인프런의 김영한님 강의 또는 토비의 스프링을 추천합니다!!