모든 인스턴스에 공통적인 기능을 수행
할 때인스턴스 생성 전에 필요한 사전 설정 작업을 수행을 하거나, 다양한 조건에 따라 다른 인스턴스를 생성해야 할 때
count
를 관리하는 간단한 예count
를 증가시키고, 모든 인스턴스에서 이 값을 조회할 수 있음class MyObject:
# 클래스 변수로 인스턴스 수를 추적
count = 0
def __init__(self):
# 인스턴스가 생성될 때마다 count를 증가시킴
MyObject.increase_count()
@classmethod
def increase_count(cls):
# 클래스 메소드를 통해 클래스 변수 접근 및 수정
cls.count += 1
@classmethod
def get_count(cls):
# 클래스 메소드를 통해 클래스 변수 값을 반환
return cls.count
# 인스턴스 생성
obj1 = MyObject()
print(MyObject.get_count()) # 출력: 1
obj2 = MyObject()
print(MyObject.get_count()) # 출력: 2
# 클래스 메소드는 인스턴스를 통해서도 호출할 수 있지만, 클래스 레벨의 작업을 수행
print(obj1.get_count()) # 출력: 2
인스턴스의 초기화 과정에 필요한 다양한 설정 값들을 준비
하거나, 특정 조건을 만족하는 객체만 생성되도록
하는 등의 용도로 사용될 수 있습니다. 객체 생성 과정을 더욱 유연하게 제어
class Database:
def __init__(self, db_type, connection_string):
self.db_type = db_type
self.connection_string = connection_string
def connect(self):
print(f"{self.db_type}에 연결: {self.connection_string}")
@classmethod
def from_config(cls, config_dict):
# 설정 사전에서 필요한 정보를 읽어옴
db_type = config_dict['db_type']
connection_string = config_dict['connection_string']
# 사전 설정에 따라 Database 인스턴스 생성
return cls(db_type, connection_string)
# 설정 사전 예시
config = {
"db_type": "MySQL",
"connection_string": "your_connection_string_here"
}
# 클래스 메서드를 사용하여 인스턴스 생성
db_instance = Database.from_config(config)
db_instance.connect()
애플리케이션의 설정이 복잡
하거나, 여러 단계의 준비 과정을 거쳐야 하는 객체를 생성해야 할 때
특히 유용Database
클래스는 데이터베이스에 연결하기 위한 정보(db_type
및 connection_string
)를 갖고 있음from_config
는 설정 정보를 담고 있는 사전을 인자로 받아, 이 정보를 기반으로 Database
인스턴스를 생성다양한 조건에 따라 다른 인스턴스를 생성하기 위해 클래스 메소드를 사용하는 방법은 객체 지향 프로그래밍에서 매우 유용
이러한 접근 방식은 특히 팩토리 메소드 패턴
에서 자주 볼 수 있으며, 객체 생성 로직을 캡슐화하여
클라이언트 코드가 직접 생성자를 호출하지 않고도 필요한 객체를 얻을 수 있게 합니다.
클래스 메소드를 사용하면, 인자에 따라 다양한 유형의 인스턴스를 조건적으로 생성할 수 있으며, 이 과정을 한 곳에서 관리할 수 있어 코드의 유연성과 가독성을 높일 수 있음
아래 예시에서는 간단한 채팅 애플리케이션을 위한 메시지 객체를 생성하는 과정을 구현
메시지 유형(텍스트 메시지, 이미지 메시지, 음성 메시지 등)에 따라 다른 인스턴스를 생성하는 클래스 메소드를 사용
class Message:
def __init__(self, content):
self.content = content
def display(self):
raise NotImplementedError("Subclass must implement abstract method")
class TextMessage(Message):
def display(self):
print(f"TextMessage: {self.content}")
class ImageMessage(Message):
def display(self):
print(f"ImageMessage: {self.content}")
class VoiceMessage(Message):
def display(self):
print(f"VoiceMessage: {self.content}")
class MessageFactory:
@classmethod
def create_message(cls, message_type, content):
if message_type == 'text':
return TextMessage(content)
elif message_type == 'image':
return ImageMessage(content)
elif message_type == 'voice':
return VoiceMessage(content)
else:
raise ValueError("Unknown message type")
# 클라이언트 코드
text_msg = MessageFactory.create_message('text', 'Hello, world!')
text_msg.display()
image_msg = MessageFactory.create_message('image', 'image_url.jpg')
image_msg.display()
voice_msg = MessageFactory.create_message('voice', 'voice_clip.mp3')
voice_msg.display()
이 예시에서 MessageFactory
클래스에 정의된 클래스 메소드 create_message
는 message_type
인자를 기반으로 조건에 따라 다른 유형의 메시지 인스턴스를 생성
이 방식을 통해 클라이언트 코드는 구체적인 메시지 유형 클래스에 의존하지 않고도 필요한 메시지 객체를 유연하게 생성할 수 있음
create_message
메소드는 간단한 조건문을 사용하여 요청된 메시지 유형에 맞는 적절한 서브클래스의 인스턴스를 반환
이 패턴은 다음과 같은 이점을 제공합니다:
MessageFactory
클래스만 수정하면 되므로 유지 보수가 용이MessageFactory
클래스)에 집중되어 있어, 복잡한 생성 조건이나 로직을 쉽게 관리할 수 있음상황을 가정해 보겠습니다. 간단한 문서 편집 애플리케이션을 개발한다고 했을 때, 다양한 종류의 문서(예: TextDocument
, DrawingDocument
, SpreadsheetDocument
등)를 생성해야 한다고 가정해 봅시다.
이 때, 팩토리 메소드 패턴을 사용하여 문서 생성 로직을 구현할 수 있습니다.
먼저, 모든 문서 타입의 부모 클래스 역할을 하는 Document
클래스와,
문서를 생성하는 메소드를 정의하는 DocumentCreator
클래스를 만듭니다.
그리고 각 문서 타입마다 DocumentCreator
의 서브 클래스를 생성하여, 해당 타입의 문서를 생성하는 로직을 구현
from abc import ABC, abstractmethod
class Document(ABC):
@abstractmethod
def use(self):
pass
class TextDocument(Document):
def use(self):
print("TextDocument: 사용 중")
class DrawingDocument(Document):
def use(self):
print("DrawingDocument: 사용 중")
class SpreadsheetDocument(Document):
def use(self):
print("SpreadsheetDocument: 사용 중")
class DocumentCreator(ABC):
@abstractmethod
def create_document(self):
pass
class TextDocumentCreator(DocumentCreator):
def create_document(self):
return TextDocument()
class DrawingDocumentCreator(DocumentCreator):
def create_document(self):
return DrawingDocument()
class SpreadsheetDocumentCreator(DocumentCreator):
def create_document(self):
return SpreadsheetDocument()
# 클라이언트 코드
def client_code(creator: DocumentCreator):
document = creator.create_document()
document.use()
# 각 문서 타입에 맞는 Creator 인스턴스를 생성하여 사용
client_code(TextDocumentCreator())
client_code(DrawingDocumentCreator())
client_code(SpreadsheetDocumentCreator())
DocumentCreator
클래스가 팩토리 메소드(create_document
)를 정의하고, 이 메소드의 구현은 각 문서 타입에 맞는 서브 클래스(TextDocumentCreator
, DrawingDocumentCreator
, SpreadsheetDocumentCreator
)에서 담당합니다. 클라이언트 코드는 DocumentCreator
인터페이스를 통해 각각의 문서 인스턴스를 생성하므로, 생성하려는 문서의 타입을 변경하고 싶을 때 해당하는 DocumentCreator
의 서브 클래스 인스턴스를 사용하면 됩니다. 이렇게 함으로써, 클라이언트 코드와 구체적인 문서 클래스 간의 결합도를 낮출 수 있습니다.