1. 객체지향 프로그래밍 이해
객체
1. 애플리케이션 내의 실체(엔티티)
2. 엔티티 간 상호작용을 통해 현실 세계의 문제를 해결할 수 있음
예: Person과 Car는 엔티티이다. Person은 Car를 운전하여 한 곳에서 다른 곳으로 이동할 수 있다
클래스
1. 클래스는 현실 세계의 엔티티를 표현할 수 있다
2. 클래스는 객체의 속성과 행위를 정의할 수 있다. 속성은 데이터 멤버이고, 행위는 멤버 함수로 표현된다
3. 클래스는 생성자를 포함한다. 이 함수의 역할은 객체에 초기 상태를 제공하는 것이다
4. 클래스는 템플릿과 같아서 재사용하기 쉽다
메소드
1. 메소드는 객체의 행위를 나타낸다
2. 메소드는 속성을 처리하여 필요한 기능을 구현할 수 있다
2. 객체지향 프로그래밍의 주요 개념
캡슐화
1. 객체의 행위가 외부 세계에게 보이지 않거나, 객체의 상태 정보가 비공개이다
2. 클라이언트는 직접 조작으로 객체의 내부 상태를 변경할 수 없다. 대신 클라이언트는 메시지를 보내 객체의 내부 상태 변경을 요청해야 한다
3. Python은 캡슐화를 위한 키워드를 제공하지 않지만, 변수나 함수 앞에 __를 붙이면 비공개 접근 속성으로 만들 수 있다
다형성
다형성은 두 가지 유형이 있다:
1. 객체가 입력 매개변수에 따라 메소드의 다른 구현을 제공한다
2. 다양한 유형의 객체가 동일한 인터페이스를 사용할 수 있다
상속
1. 상속은 한 클래스가 부모 클래스의 기능을 상속받을 수 있음을 나타낸다
2. 상속은 基类에 정의된 기능을 재사용하고 원래 소프트웨어 구현을 독립적으로 확장할 수 있는 옵션으로 설명된다 (부모 클래스 오버라이딩)
3. 상속은 다양한 객체 간의 관계를 계층 구조로 수립할 수 있고 다중 상속(여러 基类 상속)을 지원한다
추상화
1. 추상은 간단한 클라이언트 인터페이스를 제공하여, 클라이언트가 해당 인터페이스를 통해 클래스의 객체와 상호작용하고 인터페이스에 정의된 각 메소드를 호출할 수 있다
2. 추상은 내부 클래스의 복잡성을 인터페이스로 추상화하여, 클라이언트가 내부 세부 정보를 알 필요 없이 작업을 수행할 수 있게 한다
컴포지션
1. 컴포지션은 객체나 클래스를 더 복잡한 데이터 구조나 소프트웨어 구현으로 합성하는 방법이다
2. 컴포지션에서 하나의 객체가 다른 모듈의 멤버 함수를 호출할 수 있으므로, 상속 없이도 기본 기능의 모듈 간 호출을 구현할 수 있다
3. 객체지향 설계 원칙
개방/폐쇄 원칙
개방/폐쇄 원칙은 클래스나 객체 및 그 메소드가 확장에는 개방되어 있지만 수정에는 폐쇄되어 있어야 한다고 규정한다
간단히 말해, 소프트웨어 개발 시 확장해야 할 때 클래스 자체를 수정하지 않고도 클래스나 객체의 행위를 확장할 수 있도록 일반적인 방식으로 클래스나 모듈을 작성해야 한다
장점은 다음과 같다:
1. 기존 클래스가 수정되지 않으므로 호환성 문제가 발생할 가능성이 적다
2. 이전 코드의 하위 호환성을 유지하는 데 도움이 된다
역전 제어 원칙
역전 제어 원칙은 상위 수준의 모듈이 하위 수준의 모듈에 의존해서는 안 되며, 모두 추상에 의존해야 한다는 것이다
이 원칙은 두 모듈이 긴밀하게 상호 의존해서는 안 된다고 권장한다
장점은 다음과 같다:
1. 모듈 간 결합도가 약화되므로 시스템의 복잡성/경직성을 제거한다
2. 의존 모듈 간에 추상 계층이 존재하므로 모듈 간 의존 관계를 더 잘 처리할 수 있다
인터페이스 분리 원칙
인터페이스 분리 원칙은 클라이언트가 사용하지 않는 인터페이스에 의존해서는 안 된다고 규정한다
장점은 다음과 같다:
1. 개발자에게 '슬림형' 인터페이스를 작성하고 메소드와 인터페이스를 긴밀하게 관련시키도록 강제한다
2. 인터페이스에 무작위로 메소드를 추가하는 것을 방지한다
단일 책임 원칙
클래스의 책임이 단일해야 하며, 클래스가 변경되는 이유도 단일해야 한다
한 클래스가 두 가지 기능을 구현한다면, 이를 분리하는 것이最好이다. 즉, 기능이 변경의 이유가 되어야 한다
장점은 다음과 같다:
1. 기능이 변경될 때 특정 클래스만 변경하면 되고 다른 클래스는 변경할 필요가 없다
2. 클래스에 여러 기능이 있다면, 해당 클래스에 의존하는 클래스들도 다양한 이유로 변경될 수 있으므로 이러한 상황은 피해야 한다
리스코프 치환 원칙
리스코프 치환 원칙은 파생 클래스가 基類를 완전히 대체할 수 있어야 한다고 규정한다
4. 디자인 패턴 개념
디자인 패턴의 주요 특성
언어에 독립적이므로 다양한 언어로 구현할 수 있다
동적이며 새로운 패턴이 지속적으로 도입된다
사용자가 지정할 수 있다
디자인 패턴의 장점
여러 프로젝트에서 재사용할 수 있다
아키텍처 수준에서 문제를 해결할 수 있다
시간이 검증되었다
신뢰성과 의존성이 있다
디자인 패턴의 분류
코드 세그먼트: 특정 용도로 작성된 언어 코드 조각
설계: 특정 문제를 해결하기 위한 우수한 솔루션
표준: 현재 상황에 매우 일반적이고 적용 가능한 문제를 해결하는 방법
패턴: 한류의 알려진 문제를 해결할 수 있는 시간 검증된 효율적이고 확장 가능한 솔루션
컨텍스트 - 디자인 패턴의 적용 가능성
참여자: 디자인 패턴에서 사용되는 클래스로, 패턴에서 다양한 역할을 수행하여 여러 목표를 달성할 수 있다
비기능 요구사항: 메모리 최적화, 가용성, 성능 요구사항 등이 여기에 해당한다. 이러한 요소들은 전체 소프트웨어 솔루션에 영향을 미치므로 중요하다
权衡: 모든 디자인 패턴이 프로그램 개발에 적합한 것은 아니다
결과: 컨텍스트가 적합하지 않으면 디자인 패턴이 코드에 부정적인 영향을 미칠 수 있으므로, 개발자는 디자인 패턴의 결과와 용도를 이해해야 한다
패턴의 분류
생성형 패턴
(单例模式은 생성형 패턴의 예시이다)
작동 메커니즘이 객체 생성 방식에 기반한다
객체 생성의 세부 정보를 분리한다
코드가 생성하는 객체와 유형이 무관하다
연구할 수 있는 6가지 구체적인 생성형 패턴은 다음과 같다:
심플 팩토리 패턴 (Simple Factory)
팩토리 메소드 패턴 (Factory Method)
추상 팩토리 패턴 (Abstract Factory)
빌더 패턴 (Builder)
프로토타입 패턴 (Prototype)
싱글톤 패턴 (Singleton)
구조형 패턴
(어댑터 패턴은 구조형 패턴의 예시이다)
조합을 통해 강력한 기능을 가진 객체와 클래스의 구조를 설계하는 데 초점을 맞춘다
구조를 단순화하고 클래스 간 관계를 식별하는 데 중점을 둔다
클래스 상속과 컴포지션에 주로 관심이 있다
연구할 수 있는 7가지 구체적인 구조형 패턴은 다음과 같다:
퍼사드 패턴 (Facade)
어댑터 패턴 (Adapter)
프록시 패턴 (Proxy)
데코레이터 패턴 (Decorator)
브릿지 패턴 (Bridge)
컴포짓 패턴 (Composite)
플라이웨이트 패턴 (Flyweight)
행동형 패턴
(옵저버 패턴은 행동형 패턴의 예시이다)
객체 간 상호작용과 객체의 반응성에 관심을 둔다
객체가 상호작용하면서도 느슨하게 결합된 상태를 유지해야 한다
연구할 수 있는 11가지 구체적인 행동형 패턴은 다음과 같다:
템플릿 메소드 패턴 (Template Method)
옵저버 패턴 (Observer)
상태 패턴 (State)
전략 패턴 (Strategy)
职责链 패턴 (Chain of Responsibility)
커맨드 패턴 (Command)
비지터 패턴 (Visitor)
중재자 패턴 (Mediator)
메멘토 패턴 (Memento)
반복자 패턴 (Iterator)
인터프리터 패턴 (Interpreter)