나는 이렇게 본다/파이썬 디자인 패턴

디자인 패턴 개요

daco2020 2022. 5. 23. 18:52
반응형

객체지향 프로그래밍

  • 파이썬의 모든 것은 객체다. → 파이썬의 클래스 인스턴스, 변수는 개별적인 메모리 공간에 저장된다.

 

  • 객체
    • 프로그램 내의 개체(entity)를 의미
    • 개체는 다른 개체와 상호작용을 통해 목적 달성

 

  • 클래스
    • 속성(데이터)과 행동을 포함하는 객체를 정의
    • 생성자로 객체 초기 상태 설정
    • 일종의 템플릿으로 재사용 용이

 

  • 메소드
    • 객체의 행위를 의미
    • 속성을 조작하고 작업을 수행

 

 

객체지향 프로그래밍의 주요 기능

  • 캡슐화
    • 객체의 기능과 상태를 숨김
    • 클라이언트는 객체 구조와 상태를 직접 수정할 수 없고, 대신 수정을 요청
    • 요청 종류에 따라 get, set 같은 특수 함수를 사용하여 내부 상태 변경
    • 파이썬에서는 사실상 캡슐화 개념이 없지만 앞에 _를 붙여 접근 제한을 명시

 

  • 다형성
    • 객체는 함수 인자에 따라 다른 기능을 수행
    • 동일한 인터페이스를 여러 형식(타입)의 객체들이 공유
    • 파이썬은 다형성을 지원 - 예) + 연산자는 두 정수를 더하거나 문자열을 합칠 때 사용
# 정수 인덱스로 다양한 자료형에 접근할 수 있음

a = "daco"
b = (1,2,3)
c = [3,4,5]
print(a[1], b[0], c[2]

 

  • 상속
    • 부모 클래스의 기능을 이어받아 사용하거나 수정 또는 확장가능
    • 파이썬은 자바와 다르게 다중 상속을 지원한다.

 

  • 추상화
    • 정의된 함수를 호출할 수 있는 인터페이스를 제공
    • 복잡한 내부 구현에 대한 이해 없이 간편하개 인터페이스 사용
# add() 메서드로 추상화한 예시

class Adder:
    def __init__(self):
        self.sum = 0
    def add(self, value):
        self.sum += value

obj = Adder()
for i in range(100):
    obj.add(i)

print(obj.sum)

>>> 4950

 

  • 컴포지션
    • 객체나 클래스를 더 복잡한 자료 구조나 모듈로 묶는 행위
    • 컴포지션을 통해 특정 객체는 다른 모듈의 함수를 호출할 수 있다. 즉, 상속없이 외부 기능을 사용할 수 있다.
# A 클래스를 B 클래스에 포함시키는 예시

class A(object):
    def a1(self):
        print("a1")

class B(object):
    def b(self):
        print("b")
        A().a1()

objectB = B()
objectB.b()

>>> b
>>> a1

 

 

객체지향 디자인의 기본 원칙

  • 개방-폐쇄 원칙 - The Open/Close Principle
    • 클래스와 객체, 메소드 모두 확장엔 개방적이고 수정엔 폐쇄적이어야 한다.
    • 개발 단계에서 클래스나 모듈의 기능을 확장하더라도 기본 클래스는 수정하지 않도록 설계해야 한다.
    • 기본 클래스는 건드리지 않고 클래스를 확장해 새로운 기능을 추가 구현할 수 있는 구조를 의미함.
    • 장점
      • 기본 클래스를 수정하지 않기 때문에 실수가 줄어든다.
      • 기존 코드의 호환성을 보장한다.

 

  • 제어 반전 원칙 - The Inversion of Control Principle
    • 상위 모듈은 하위 모듈에 의존적이지 않아야 한다.
    • 세부 구현이 추상화에 의존해야한다. 그 반대는 바람직하지 않다.
    • 모듈은 지나치게 상호 의존하면 안 된다. 의존적인 모듈 사이에 추상화 계층으르 둬 분리해야 한다.
    • 장점
      • 모듈 간 낮은 상호 의존도는 시스템 복잡도를 줄인다.
      • 추상화 계층 덕분에 모듈 간 상호 관계를 쉽게 관리할 수 있다.

 

  • 인터페이스 분리 원칙 - The Interface Segregation Principle
    • 클라이언트는 불필요한 인터페이스에 의존하지 않아야 한다는 원칙
    • 개발자는 반드시 해당 기능과 관련 있는 메소드만을 작성해야 한다.
    • 불필요한 인터페이스는 불필요한 메소드을 구현하도록 만든다.
    • 예를들어 피자 인터페이스에 치킨 메소드가 있어서는 안된다.
    • 장점
      • 인터페이스에 특화된 메소드만 있는 가벼운 인터페이스를 작성하게 된다.
      • 의도하지 않은 메소드를 구현하지 않아도 된다.

 

  • 단일 책임 원칙 - The Single Responsibility Principle
    • 클래스는 하나의 책임만을 가져야한다.
    • 한 가지 기능에만 중점을 둬야 한다.
    • 두 가지 이상의 기능이 필요하다면 클래스를 나누자.
    • 클래스를 수정하는 이유가 특정 기능 때문이라면 괜찮지만, 두 가지 이상의 이유 때문이라면 클래스 자체를 나눠야 한다.
    • 장점
      • 특정 기능을 수정할 때 관련 클래스 외에는 건드릴 필요가 없다.
      • 한 개의 클래스에 여러 가지 기능이 있다면 관련된 모든 내요오을 수정해야 하는 상황이 발생할 수 있음

 

  • 치환 원칙 - The Substitution Principle
    • 상속받는 클래스는 기본 클래스의 역할을 완전히 치환할 수 있어야 한다는 원칙이다.

 

 

 

디자인 패턴의 개념

  • 디자인 패턴의 장점
    • 여러 프로젝트에서 재사용 될 수 있음
    • 설계 문제를 해결할 수 있다.
    • 오랜 시간에 걸쳐 유효성이 입증됐다.

 

  • 디자인 패턴 용어
    • 스니펫 : 데이터베이스에 연결하는 코드 등의 특수한 목적을 위한 코드
    • 디자인 : 문제에 대한 해결책
    • 스탠다드 : 문제를 해결하는 대표적인 방식
    • 패턴 : 유효성이 검증된 해결책
    • 참가자 : 디자인 패턴에 사용되는 클래스를 의미, 각 클래스는 다른 역할을 한다.
    • 비기능적 조건 : 메모리 최적화와 사용성, 성능을 말하며 솔루션 전체에 영향을 미치는 핵심 요소다.
    • 타협선 : 디자인 패턴이 모든 상황에 맞는 것은 아니므로 타협을 통해 디자인 패턴 사용을 결정하는 부분

 

  • 동적 언어 패턴 - 파이썬의 특징
    • 자료형과 클래스는 런타임 객체이다.
    • 변수 값과 타입 또한 런타임에 변경될 수 있다.
    • 동적 언어는 클래스 제한 측면에서 더 유동적이다. (ex, 다형성, public)

 

  • 디자인 패턴의 분류
    • 생성 패턴
      • 객체가 생성되는 방식을 중시
      • 객체 생성 관련 로직을 숨긴다.
      • 코드는 생성하려는 객체형과는 독립적이다.
      • 예 - 싱글톤 패턴
    • 구조 패턴
      • 클래스와 객체를 더 큰 결과물로 합칠 수 있는 구조로 설계
      • 구조를 간결화하고 객체 간의 상호관계를 파악할 수 있음
      • 클래스 상속과 컴포지션을 중시한다.
      • 예 - 어댑터 패턴
    • 행위 패턴
      • 객체 간의 상호작용과 책임을 중시
      • 객체는 상호작용하지만 느슨하게 결합
      • 예 - 옵서버 패턴
반응형