스프링 기본 - 객체지향 적용/ DI, loC

2023. 2. 15. 13:46spring/core

객체 지향 5가지 원칙 (SOLID)

  • SRP (Single Responsibility Principle) 단일 책임의 원칙

- 모듈이 변경되는 이유가 한가지여야 한다.

- 즉, 해당 모듈이 여러 대상 또는 액터들에 대해 책임을 가져서는 안되고, 오직 하나의 액터에 대해서만 책임을 져야 한다.


  • OCP (Open-Closed Principle) 개방 폐쇄 원칙

- 확장에 대해 열려있고 변경에 대해서는 닫혀있어야 한다.

- 개방 폐쇄 원칙을 지키기 위해서는 추상화에 의존해야 한다.


  • ISP (Interface segregation principle) 인터페이스 분리 원칙

-  목적과 관심에 따라 인터페이스로 분리한다.

- 자신의 관심에 맞는 인터페이스만을 접근하여 불필요한 간섭을 최소화한다.


  • LSP (Liskov Substitution Principle) 리스코프 치환 원칙

- 상속 관계의 특징을 정의하기 위해 발표

- 해당 객체를 사용하는 클라이언트는 상위 타입이 하위 타입으로 변경되어도, 차이점을 인식하지 못한 채 상위 타입의 퍼블릭 인터페이스를 통해 서브 클래스를 사용할 수 있어야 한다는 것이다.


  • DIP (Dependency Inversion Principle) 의존 역전 원칙

- 입력과 출력으로부터 가까운 모듈(저수준 모듈)은 비즈니스와 관련된 모듈(고수준 모듈)에 의존해야 한다.

- 컴파일 시점에 올바른 의존 관계를 설계한다.


상황 : 클라이언트가 주문 --> 클라이언트의 등급에 따라 할인이 적용됨.

 

* 할인 정책은 두 가지로 나누어짐 (고정 할인 (1000원) / 비율 할인 (10%) )

* 프로젝트 의뢰자의 요구에 따라 교체해주어야 함.

 

1. 

public class OrderServiceImpl implements OrderService {

//    private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
    private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
    private final MemberRepository memberRepository = new MemoryMemberRepository();

---> 추상뿐만 아니라 구현 클래스에도 의존하고 있다. <DIP 위반>

추상(인터페이스) : DiscountPolicy

구현 클래스 : FixDisCountPolicy, RateDiscountPolicy

 

---> 기능을 확장하거나 변경하려면 OrderServiceImpl의 코드를 변경해야 함. <OCP 위반>

 

 

따라서 OrderServiceImpl 은 인터페이스만 의존하도록 해야 한다.

 

2.

public class OrderServiceImpl implements OrderService {

    private DiscountPolicy discountPolicy;
    private MemberRepository memberRepository;

이대로 끝내면 NullPointException이 발생하게 된다 ! (주입 필요)

 

DI (Dependency Injection) 의존관계 주입

public class OrderServiceImpl implements OrderService {
    private DiscountPolicy discountPolicy;
    private MemberRepository memberRepository;
    public OrderServiceImpl(DiscountPolicy discountPolicy, MemberRepository memberRepository) {
        this.discountPolicy = discountPolicy;
        this.memberRepository = memberRepository;
    }
public class AppConfig {
    public MemberService memberService(){
        return new MemberServiceImpl(new MemoryMemberRepository());
    }
    public OrderService orderService(){
        return new OrderServiceImpl(
                new FixDiscountPolicy(),
                new MemoryMemberRepository());
    }
}
memberService = appConfig.memberService();
 orderService = appConfig.orderService();

각각 클래스는 인터페이스만 의존하고 생성자를 열어둔다.

AppConfig라는 클래스에서 모든 주입을 담당한다. 변경할 일이 생기면 AppConfig에서만 변경해주면 된다.

 

AppConfig 리펙터링

public class AppConfig {
    public MemberService memberService(){
        return new MemberServiceImpl(memberRepository());
    }
    public OrderService orderService(){
        return new OrderServiceImpl(discountPolicy(), memberRepository());
    }
    
    private MemberRepository memberRepository(){
        return new MemoryMemberRepository();
    }
    
    public DiscountPolicy discountPolicy(){
        return new FixDiscountPolicy();
    }
}

loC (Inversion of Control) 제어의 역전

프로그램 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것을 제어의 역전(loC)라고 한다.

ex) OrderServiceImpl (직접) ---> AppConfig (외부)  제어권 이동

 

DI (Dependency Injection) 의존관계 주입

애플리케이션 실행 시점(런타임)에 외부에서 실제 구현 객체를 생성하고 클라이언트에 전달해서 클라이언트와 서버의 실제 의존관계가 연결되는 것을 의존관계 주입(DI)라고 한다.

 


DI 스프링으로 변경 

3.

@Configuration
public class AppConfig {
    @Bean
    public MemberService memberService(){
        return new MemberServiceImpl(memberRepository());
    }
    @Bean
    public OrderService orderService(){
        return new OrderServiceImpl(discountPolicy(), memberRepository());
    }

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

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

* 빈 이름은 메서드 이름

* @Bean(name="memberService2) 처럼 직접 부여 가능

 

사용방법 

ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
ac.getBean(빈이름, 타입)
ac.getBean(타입)

 

* 타입은 추상, 빈이름은 구현체가 정석

 

* 부모 타입을 조회하면 자식  타입은 함께 조회된다.

'spring > core' 카테고리의 다른 글

스프링 기본 - 싱글톤  (0) 2023.02.15