[기본]객체지향 프로그래밍

1. 객체 지향과 다형성

객체지향 프로그래밍이란

실생활 객체를 모방하여 프로그래밍 하는 방법으로, 속성(변수)와 기능(메서드)를 갖는다. 자바는 객체 지향 언어로서 Class 를 통해 객체를 정의하고 생성하여 사용한다.

객체 지향 특징

  • 추상화 : 공통의 속성이나 기능으로 묶는 것. 자바에선 인터페이스의 존재가 추상화에 해당한다.
  • 캡슐화 : 객체의 속성과 기능을 변수와 메서드로 묶어 클래스에 구현하고, 실제 구현은 은닉한다.
  • 상속 : 부모 클래스로부터 상속한 클래스를 통해 세분화된 객체를 생성한다.
  • 다형성
    • 부모 참조변수가 자식 인스턴스 참조할 수 있는 것.
    • 오버로딩을 통해 같은 이름의 메서드가 매개변수에 따라 다양한 기능 수행하도록 하는 것.
    • 오버라이딩을 통해 자식이 부모 메서드를 재정의해 다른 용도로 사용 하는것.

다형성

다형성의 존재로 부모 참조변수가 자식 인스턴스 참조가 가능하다.
자바는 기능만을 추상화하여 부모 인터페이스로, 자식을 구현클래스로 하여 이를 활용한다.
실생활에 비유하면 부모 인터페이스는 역할. 자식 구현클래스는 기능이다.
예를 들면 인터페이스를 자동차. 구현클래스를 K3, 아반떼 라고 하자.
운전자는 모든 차의 운전 방식은 똑같기 때문에 차종을 몰라도 운전 기술만 익히면 된다. 또한 차가 바뀐다고 해도 운전자가 운전을 새로 배울 필요가 없다.


2. 좋은 객체 지향 설계의 5원칙

SOLID

  1. SRP 단일 책임 원칙
    • 한 클래스는 하나의 책임만 가져야함
    • 이에 따라 한 클래스가 변경되도 타 클래스의 변경이 적어야 한다.
    • JSP에 여러 MVC 기능을 모두 때려박는 Model1 방식은 SRP를 위배한 경우이다.
  1. OCP 개방-폐쇄 원칙
    • 개발시 확장에는 열려있으나 변경에는 닫혀있어야한다. 즉 기능을 확장해도 변경이 있으면 안됨.
    • 다형성을 활용하자. 부모 참조변수로 모든 기능을 구현해놓고, 확장시 자식 인스턴스만 바꿔 끼우면 확장시 변경이 없지 않을까
    • MemberService 클래스에서 MemberRepository 객체를 사용한다고 하자. MemberService의 모든 기능을 MemberRepository로 구현하고 DB가 바뀌면 MemberRepository의 인스턴스만 바꿔끼우도록 하면 되지 않을까?
    • 결국 사용하기 위해 MemberRepository 객체를 생성할 때 참조변수를 통한 인스턴스 생성 구문이 바뀌기 때문에 다른 구현 클래스를 쓰려면 MemberService도 바꿔야한다.
public class MemberService {
	//private MemberRepository memberRepository = new MemoryMemberRepository();
    	private MemberRepository memberRepository = new JdbcMemberRepository();
}
  1. LSP 리스코프 치환 원칙
    • 다형성의 하위 클래스는 인터페이스 규약을 다 지켜야 한다.
    • 인터페이스의 Excel() 메서드가 다른 모든 구현클래스에서는 속도가 증가하는데, 특정 구현클래스가 속도 감소하게 구현되어있으면 LSP 위반.
  2. ISP 인터페이스 분리 원칙
    • 인터페이스를 여러개로 분화하여 유지보수를 용이하게 하여야 한다.
  3. DIP 의존관계 역전 원칙
    • 클라이언트는 구현 클래스가 아닌 인터페이스에 의존한다.
    • 클라이언트에서는 부모 인터페이스를 참조변수로 하는 객체를 사용하며. 구현 클래스가 변경되도 변경 없이 사용하여야 한다는 뜻
    • 위의 예시에서 MemberRepository 의 구현 클래스가 변경되면 MemberService도 변경되어야 하기때문에 위배된다.

3. 정리

다형성의 한계

부모 인터페이스인 MemberRepository를 참조변수로 하는 객체를 사용해 모든 MemberService를 구현할 수 있다.
그런데 MemberRepository 의 인스턴스가 바뀌게되면 객체 생성부분을 수정해야한다.
따라서 구현체가 바뀌면 클라이언트 코드도 바꿔야 하는 문제 가 생긴다.

스프링이 하는 일

스프링은 DI 컨테이너DI를 통해 의존성을 스프링이 관리한다. 따라서 의존 객체를 생성하지 않고 사용할 수 있게 하여. 구현체가 바뀔 때 객체 생성 부분을 수정해야하는 문제를 예방한다.



본 글은 김영한님의 "스프링 핵심 원리 - 기본편" 강의내용 및 이해한 내용을 정리한 것입니다.

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8

좋은 웹페이지 즐겨찾기