728x90
24.09.03 CS, C++
CS
추상 팩토리(Abstract Factory)
- 추상 팩토리 패턴은 연관성이 있는 객체 군이 여러개 있을 경우 이들을 묶어 추상화하고, 어떤 구체적인 상황이 주어지면 팩토리 객체에서 집합으로 묶은 객체 군을 구현화 하는 생성 패턴이다. 클라이언트에서 특정 객체를 사용할 때 팩토리 클래스만을 참조하여 특정 객체에 대한 구현부를 감추어 역할과 구현을 분리시킬 수 있다.
- 즉, 추상 팩토리의 핵심은 제품군 집합을 타입 별로 찍어낼 수 있다는 점이 포인트이다. 복잡하게 묶이는 제품군들을 관리와 확장하기 용이하게 패턴화 한 것이 추상 팩토리이다.
추상 팩토리 패턴 구조
- AbstractFactory
- 최상위 공장 클래스. 여러개의 제품들을 생성하는 여러 메소드들을 추상화 한다.
- ConcreteFactory
- 서브 공장 클래스들은 타입에 맞는 제품 객체를 반환하도록 메소드들을 재정의한다.
- AbstractProduct
- 각 타입의 제품들을 추상화한 인터페이스
- ConcreteProduct (Product A - Product B)
- 각 타입의 제품 구현체들. 이들은 팩토리 객체로부터 생선된다.
- Client
- Client는 추상화된 인터페이스만을 이용하여 제품을 받기 때문에, 구체적인 제품, 공장에 대해서는 모른다.
Abstract Factory vs Factory Method
- 둘다 팩토리 객체를 통해 구체적인 타입을 감추고 객체 생성에 관여하는 패턴 임에는 동일하다. 또한 공장 클래스가 제품 클래스를 각각 나뉘어 느슨한 결합 구조를 구성하는 모습 역시 둘이 유사하다.
- 그러나 주의할 것은 추상 팩토리 패턴이 팩토리 메서드 패턴의 상위 호환이 아니라는 점이다. 두 패턴의 차이는 명확하기 때문에 상황에 따라 적절한 선택을 해야 한다.
- 예를들어 팩토리 메서드 패턴은객체 생성 이후 해야 할 일의 공통점을 정의하는데 초점을 맞추는 반면, 추상 팩토리 패턴은 생성해야 할객체 집합 군의 공통점에 초점을 맞춘다.
- 단, 이 둘을 유사점과 차이점을 조합해서 복합 패턴을 구성하는 것도 가능하다.
추상 팩토리 패턴 특징
- 패턴 사용 시기
- 관련 제품의 다양한 제품 군과 함께 작동해야 할때, 해당 제품의 구체적인 클래스에 의존하고 싶지 않은 경우
- 여러 제품군 중 하나를 선택해서 시스템을 설정해야하고 한 번 구성한 제품을 다른 것으로 대체할 수도 있을 때
- 제품에 대한 클래스 라이브러리를 제공하고, 그들의 구현이 아닌 인터페이스를 노출시키고 싶을 때
- 패턴 장점
- 객체를 생성하는 코드를 분리하여 클라이언트 코드와 결합도를 낮출 수 있다.
- 제품 군을 쉽게 대체 할 수 있다.
- 단일 책임 원칙 준수
- 개방/폐쇄 원칙 준수
- 패턴 단점
- 각 구현체마다 팩토리 객체들을 모두 구현해주어야 하기 때문에 객체가 늘어날 때 마다 클래스가 증가하여 코드의 복잡성이 증가한다.(팩토리 패턴의 공통적인 문제점)
- 기존 추상 팩토리의 세부사항이 변경되면 모든 팩토리에 대한 수정이 필요해진다. 이는 추상 팩토리와 모든 서브클래스의 수정을 가져온다.
- 새로운 종류의 제품을 지원하는 것이 어렵다. 새로운 제품이 추가되면 팩토리 구현 로직 자체를 변경해야 한다.
C++
- C++에서는 코드를 효율적으로 관리하고 재사용성을 높이기 위해 헤더 파일(header file)과 소스 파일(source file, .cpp 파일)로 코드를 나눈다. 각각의 파일은 특정한 역할을 하며, 올바르게 사용하면 프로젝트의 유지 보수성과 확장성을 크게 향상시킬 수 있다.
1. 헤더 파일(.h 또는 .hpp 파일)
- 헤더 파일은 클래스, 함수, 전역 변수, 매크로 등의 선언(declaration)을 포함하는 파일이다. 컴파일러는 헤더 파일을 통해 코드의 구조를 파악하고, 다른 파일에서 이를 사용할 수 있게 한다. 헤더 파일은 보통 .h 또는 .hpp 확장자를 가진다.
헤더 파일의 주요 역할
- 클래스와 함수의 선언
- 헤더 파일에는 클래스 정의의 선언부, 함수 프로토타입, 전역 변수의 선언 등이 포함된다.
- 중복 정의 방지
- 헤더 파일은 보통 여러 소스 파일에서 포함되기 때문에, 전처리 지시자(preprocessor directive)를 사용하여 중복 포함을 방지해야 한다.
헤더 파일의 구조
- 일반적인 헤더 파일의 구조는 다음과 같다:
cpp코드 복사
#ifndef MYCLASS_H // 헤더 가드 시작#define MYCLASS_H
class MyClass {
public:
MyClass(); // 생성자 선언
void myFunction(); // 멤버 함수 선언
private:
int myVariable; // 멤버 변수 선언
};
#endif // 헤더 가드 끝
- 헤더 가드(Header Guard)
- #ifndef, #define, #endif 지시자를 사용하여 중복 포함을 방지한다. 이는 해당 헤더 파일이 한 번만 포함되도록 보장한다.
- 클래스 선언
- MyClass 클래스의 선언을 포함한다. 생성자와 멤버 함수가 선언되지만, 정의는 포함되지 않는다.
헤더 파일에 포함할 내용
- 헤더 파일에는 주로 다음과 같은 내용이 포함된다:
- 클래스 선언
- 클래스의 멤버 변수와 멤버 함수의 선언만 포함한다.
- 함수 프로토타입
- 함수의 반환형과 매개변수를 포함한 선언만 제공한다.
- 전역 변수와 상수 선언
- extern 키워드를 사용해 전역 변수의 선언을 포함할 수 있다.
- 템플릿 선언
- 템플릿 클래스를 선언하고 정의할 수 있다.
- 전처리 매크로
- 매크로 정의를 통해 상수를 정의하거나 조건부 컴파일을 사용할 수 있다.
2. 소스 파일(.cpp 파일)
- 소스 파일은 함수와 클래스 멤버 함수의 정의(implementation)를 포함하는 파일이다. 소스 파일은 실제 코드가 실행되는 부분이며, 보통 .cpp 확장자를 가진다.
소스 파일의 주요 역할
- 함수와 클래스 멤버 함수의 정의
- 헤더 파일에 선언된 함수와 클래스 멤버 함수의 정의를 포함한다.
- 코드 로직 구현
- 소스 파일은 코드의 실제 로직을 구현하며, 컴파일된 결과물에 포함된다.
- 헤더 파일 포함
- 소스 파일은 필요한 헤더 파일을 #include 지시자를 사용하여 포함한다.
소스 파일의 구조
- 일반적인 소스 파일의 구조는 다음과 같다:
cpp코드 복사
#include "MyClass.h" // 헤더 파일 포함// MyClass 생성자 정의
MyClass::MyClass() {
myVariable = 0;
}
// MyClass의 멤버 함수 정의
void MyClass::myFunction() {
// 함수의 실제 코드
}
- 헤더 파일 포함
- #include "MyClass.h"와 같은 지시자를 사용하여, 클래스와 함수 선언을 포함하는 헤더 파일을 가져온다.
- 클래스 멤버 함수 정의
- MyClass::MyFunction()과 같은 형식으로 멤버 함수가 정의된다. 이 부분에서 실제 함수의 동작을 구현한다.
3. 헤더 파일과 소스 파일의 관계
- 헤더 파일은 선언(declaration)을 제공하고, 소스 파일은 정의(definition)를 제공한다. 즉, 헤더 파일에는 "어떤 것이 있다"는 정보를 제공하고, 소스 파일은 "어떻게 동작하는지"에 대한 정보를 제공한다.
- 여러 소스 파일이 같은 헤더 파일을 포함할 수 있다. 이 경우 헤더 가드를 사용해 중복 정의로 인한 컴파일 오류를 방지한다.
- 소스 파일은 필요한 헤더 파일을 #include 지시자를 사용하여 가져오며, 컴파일 시점에 해당 파일의 내용을 소스 파일에 포함시킨다.
4. #include 지시자
- #include 지시자는 파일의 내용을 포함시키는 역할을 한다. #include는 두 가지 형태로 사용할 수 있다:
- #include "MyClass.h": 사용자 정의 헤더 파일을 포함할 때 사용한다. 이 형식은 현재 디렉토리 또는 프로젝트 디렉토리에서 파일을 찾는다.
- #include <iostream>: 표준 라이브러리 헤더 파일을 포함할 때 사용한다. 이 형식은 컴파일러가 설치된 위치에서 파일을 찾는다.
5. 프로젝트의 구조화
- C++ 프로젝트를 구조화할 때는 다음과 같은 규칙을 따르는 것이 좋다
- 헤더 파일과 소스 파일을 분리
- 각 클래스는 하나의 헤더 파일과 하나의 소스 파일로 구성한다. 예를 들어, Player 클래스가 있다면 Player.h와 Player.cpp 파일을 생성한다.
- 모듈화(Modularity)
- 관련된 클래스와 함수는 같은 폴더에 두어 모듈 단위로 관리한다.
- 헤더 파일 최소화
- 불필요한 헤더 파일의 포함을 최소화하여 컴파일 시간을 줄인다.
6. 헤더 파일의 상호 참조 문제
- 두 헤더 파일이 서로를 참조할 때 상호 참조 문제(Circular Dependency)가 발생할 수 있다. 이를 해결하기 위해 전방 선언(forward declaration)을 사용한다. 예를 들어, 클래스 A와 B가 서로 참조해야 하는 경우
cpp코드 복사
// A.h
#ifndef A_H
#define A_H
class B; // 전방 선언
class A {
B* b; // 포인터로 참조
};
#endif // A_H
cpp코드 복사
// B.h
#ifndef B_H
#define B_H
#include "A.h" // A.h를 포함class B {
A* a; // 포인터로 참조
};
#endif // B_H
이렇게 하면 상호 참조 문제를 방지할 수 있다.
728x90
'Study > TIL(Today I Learned)' 카테고리의 다른 글
24.09.05 CSAPP복습 ,C++ (0) | 2024.09.05 |
---|---|
24.09.04 CS, C++ (0) | 2024.09.04 |
24.09.02 CS, 언리얼 (1) | 2024.09.02 |
24.08.30 CS, C++ (0) | 2024.08.30 |
24.08.29 CS, C++ (0) | 2024.08.29 |