[기초 공부] 객체 지향 프로그래밍 정리

woodyn·2021년 5월 18일
0

기초 공부

목록 보기
5/16
post-thumbnail

객체 지향 프로그래밍

실세계의 객체처럼 모델링하고, 객체와의 상호작용을 토대로 프로그래밍하는 기법

객체 지향 언어의 특징

캡슐화(Encapsulation)

데이터와 그 데이터를 다루는 함수를 묶고, 외부의 개입과 오용을 막는 것

  • 정보 은닉을 실현: 구현을 숨기고 안정적인 인터페이스를 제공함으로써, 디자인 변경에 대비함 (decoupling)

조합(Composition)

객체 내에 다른 객체의 인스턴스를 필드로 갖도록 하는 것 (HAS-A 관계)

  • 다른 객체들로 이루어진 하나의 객체를 통해 새로운 인터페이스를 제공함

상속(Inheritance)

클래스들이 계층 구조를 갖고, 부모 디자인을 물려받는 것 (IS-A 관계)

  • 기존 코드를 재사용할 수 있음
  • 기존 코드와 독립적으로 확장할 수 있음

다형성(Polymophism)

하나의 인터페이스로 여러 종류의 함수나 클래스를 제공하는 것

  • 코드 실행 시 어떤 개체에서 실행될지 신경쓸 필요 없도록(agnostic) 함
  • 애드 혹(Ad hoc) 다형성: 함수에 대한 다형성 (오버로딩)
  • 파라매트릭(Parametric) 다형성: 여러 타입을 다루는 함수와 클래스에 대한 다형성 (Generic)
  • 서브타입(Subtype) 다형성: 클래스에 대한 다형성 (메소드 오버라이딩)

SOLID 원칙

소프트웨어 설계를 이해하기 쉽고, 유연하고, 유지 보수에 용이하도록 만들기 위한 원칙들

단일 책임 원칙(SRP; Single responsibility)

클래스를 수정하는 이유는 오직 한 가지여야만 한다.

  • 모든 클래스와 함수는 한 가지 목적만을 가지며, 이를 캡슐화해야 한다.
  • 여러 기능이 결합되도록 설계하면, 한 가지 기능을 수정할 때 다른 기능도 수정해야만 한다.

개방-폐쇄 원칙(OCP; Open-closed)

클래스와 함수는 확장에 열려있으나, 수정에는 닫혀있어야 한다.

  • 다른 곳에서 사용되기 위해 수정에 닫혀있어야 한다. (잘 정의된 인터페이스를 통한 정보 은닉)
  • 새로운 기능을 추가하기 위해 확장에 열려있어야 한다. (기존 코드를 바꾸지 않고 상속)

리스코브 치환 원칙(LSP; Liskov substitution)

기반 클래스에 대한 함수는 파생 클래스에 대해서도 작동해야 한다.

  • 부모 클래스를 사용하는 코드에서, 부모 클래스를 자식 클래스로 치환해도 작동해야 한다.
  • 즉, 부모 메소드의 Precondition을 강화하거나, Postcondition을 약화해선 안 된다.
    • Precondition을 강화하면, 더 적은 범위의 인자만을 허용하게 된다.
      • 기존에 허용됐던 인자를 사용하는 코드가 고장난다. (이거 넣어도 됐었는데?)
    • Postcondtion을 약화하면, 더 넓은 범위의 반환 값을 허용하게 된다.
      • 기존 범위의 반환 값에만 대응했던 코드가 고장난다. (이런 것만 나올 줄 알았는데?)

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

범용적인 인터페이스 하나보다 구체적인 인터페이스 여러 개가 낫다.

  • 부모 클래스에게 상속받은 메소드 중 사용하지 않는 것이 있으면 안 된다.
  • 즉, 너무 큰 인터페이스를 작은 인터페이스 여러 개로 나누고, 클라이언트가 그들 중 하나에 의존하도록 해야 한다.
    • 클라이언트 코드가 꼭 필요한 핵심에만 의존하도록 만든다. (decoupling)
    • 시스템이 너무 결합(coupled)되어 있으면, 한 부분을 수정하기 위해 다른 많은 부분을 건드려야만 할 것이다.

의존 역전 원칙(DIP; Dependency inversion)

구현보다 추상적 개념에 의존하라.

  • 상위 계층 모듈이 하위 계층 모듈에 직접 의존해선 안 된다. 둘 다 추상화된 개념(interface)에 의존해야 한다.
  • 추상화된 개념이 구체적인 구현에 의존해선 안 된다. 그 반대로, 구현이 추상에 의존해야 한다.
    • 즉, 하위 계층 모듈(Object B)이 상위 계층 모듈(Interface A)을 의존하게 된다.
    • 기존의 top-to-bottom에서 역전된 bottom-to-top 모습의 의존 관계를 보인다.

디자인 패턴

소프트웨어 디자인 시 자주 발생하는 문제를 위한 해결책

생성(Creational) 패턴

객체 생성을 위한 패턴

Abstract factory 패턴

객체를 생성하는 팩토리 클래스를 추상화

  • 추상화된 것에 의존하도록 함

Builder 패턴

복잡한 객체의 생성 과정을 분리

Factory method 패턴

객체 생성을 캡슐화

  • 추상화된 것에 의존하도록 함

Prototype 패턴

미리 만들어둔 뼈대 객체를 기반으로 새로운 객체 생성

  • 성능과 메모리 사용량을 최소화함

Singleton 패턴

클래스가 오직 하나의 인스턴스만을 갖도록 함

  • 생성 비용을 아끼고 데이터를 쉽게 공유할 수 있음
  • 단점: 객체 지향적이지 않고, TDD가 어려워짐
    • 클래스 상속이 불가능함
    • 의존성을 주입받기 어려움
    • 매 테스트마다 싱글톤 객체의 깨끗함을 보장할 수 없음

구조(Structural) 패턴

클래스 구조 설계를 위한 패턴

Composite 패턴

트리 구조처럼 부분-전체 계층 구조를 구성함 (e.g. 파일-디렉토리)

Decorator 패턴

객체를 감싸 동적으로 새로운 기능을 추가함

  • 상속보다 유연한 구조를 만들 수 있음

Proxy 패턴

객체를 감싸고 해당 클래스를 상속하여, 객체를 접근하는 메소드에 새로운 기능을 추가함

행동(Behavioural) 패턴

객체 간 상호작용을 위한 패턴

Command 패턴

클라이언트의 다양한 요청을 캡슐화

Observer(Publish/subscribe) 패턴

1:N 의존 관계로, 한 객체의 상태 변경을 다른 객체들에게 알림

Strategy 패턴

수행할 알고리즘을 캡슐화하고 서로 교체할 수 있도록 함

  • 클라이언트와 알고리즘 간의 의존성을 약화함

Template Method 패턴

수행할 알고리즘의 뼈대를 만들어두고, 자식 클래스가 특정 부분을 정의하도록 함

profile
🦈

0개의 댓글