Skip to main content

νŒ©ν† λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄ μ΄ν•΄ν•˜κΈ°

1. νŒ¨ν„΄ κ°œμš”β€‹

νŒ©ν† λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄(Factory Method Pattern)은 객체 생성 μ½”λ“œμ˜ 쀑볡과 μ˜μ‘΄μ„±μ„ 쀄이고, μ½”λ“œμ˜ ν™•μž₯성을 높이기 μœ„ν•΄ μ‚¬μš©λ˜λŠ” λ””μžμΈ νŒ¨ν„΄μž…λ‹ˆλ‹€. μ΄λŠ” λ™μΌν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ”°λ₯΄λŠ” μ—¬λŸ¬ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œ, ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œκ°€ ν•΄λ‹Ή ν΄λž˜μŠ€λ“€μ˜ ꡬ체적인 κ΅¬ν˜„ λ‚΄μš©μ„ μ•Œ ν•„μš” 없이 μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 μžˆλ„λ‘ λ•μŠ΅λ‹ˆλ‹€.

2. 문제 상황 μ˜ˆμ‹œβ€‹

기본적인 μ½”λ“œ ꡬ쑰​

class Truck:
def deliver(self):
return "νŠΈλŸ­μ„ 타고 μš΄λ°˜ν•œλ‹€"

class Ship:
def deliver(self):
return "λ°°λ₯Ό 타고 μš΄λ°˜ν•œλ‹€"

# μš΄μ†‘ μˆ˜λ‹¨μ„ λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜
def get_transport(transport_type):
if transport_type == TransportType.TRUCK:
return Truck()
elif transport_type == TransportType.SHIP:
return Ship()

# μ‚¬μš© μ˜ˆμ‹œ
transport1 = get_transport(TransportType.TRUCK)
print(transport1.deliver()) # "νŠΈλŸ­μ„ 타고 μš΄λ°˜ν•œλ‹€"

transport2 = get_transport(TransportType.SHIP)
print(transport2.deliver()) # "λ°°λ₯Ό 타고 μš΄λ°˜ν•œλ‹€"

TransportType Enum 좔가​

νŒŒλΌλ―Έν„° μž…λ ₯을 μ•ˆμ „ν•˜κ²Œ ν•˜κΈ° μœ„ν•΄ λ¬Έμžμ—΄ λŒ€μ‹  Enum을 μ‚¬μš©ν•©λ‹ˆλ‹€.

from enum import Enum

class TransportType(Enum):
TRUCK = "truck"
SHIP = "ship"
AIRPLANE = "airplane"

μƒˆλ‘œμš΄ μš”κ΅¬μ‚¬ν•­ 좔가​

λ§Œμ•½ μƒˆλ‘œμš΄ μš΄μ†‘ μˆ˜λ‹¨μΈ λΉ„ν–‰κΈ°λ₯Ό μΆ”κ°€ν•œλ‹€κ³  κ°€μ •ν•΄ λ΄…μ‹œλ‹€.

class Airplane:
def deliver(self):
return "λΉ„ν–‰κΈ°λ₯Ό 타고 μš΄λ°˜ν•œλ‹€"

get_transport ν•¨μˆ˜μ— λΉ„ν–‰κΈ° νƒ€μž…μ„ μΆ”κ°€ν•©λ‹ˆλ‹€.

# νŒ©ν† λ¦¬ λ©”μ„œλ“œμ— μƒˆ νƒ€μž… μΆ”κ°€
if transport_type == TransportType.AIRPLANE:
return Airplane()

3. νŒ©ν† λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄ λ„μž…β€‹

νŒ©ν† λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λ©΄ 객체 생성 λ‘œμ§μ„ λ³„λ„μ˜ 클래슀 λ˜λŠ” λ©”μ„œλ“œλ‘œ λΆ„λ¦¬ν•˜μ—¬ ν™•μž₯성을 높일 수 μžˆμŠ΅λ‹ˆλ‹€.

κΈ°λ³Έ ꡬ쑰​

  1. Transport μΈν„°νŽ˜μ΄μŠ€(좔상 클래슀): λͺ¨λ“  μš΄μ†‘ μˆ˜λ‹¨ ν΄λž˜μŠ€κ°€ κ³΅ν†΅μ μœΌλ‘œ κ΅¬ν˜„ν•΄μ•Ό ν•  λ©”μ„œλ“œλ₯Ό μ •μ˜ν•©λ‹ˆλ‹€.
  2. ꡬ체적인 μš΄μ†‘ 클래슀(Truck, Ship, Airplane λ“±): Transportλ₯Ό 상속받아 deliver() λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•©λ‹ˆλ‹€.
  3. νŒ©ν† λ¦¬ 클래슀: 객체 생성 μ±…μž„μ„ λ‹΄λ‹Ήν•˜μ—¬, νŠΉμ • μš΄μ†‘ μˆ˜λ‹¨μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€.

μ½”λ“œ κ΅¬ν˜„ μ˜ˆμ‹œβ€‹

# 좔상 클래슀 (κΈ°λ³Έ ꡬ쑰 μ •μ˜)
class Transport:
def deliver(self):
raise NotImplementedError("deliver λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•΄μ•Ό ν•©λ‹ˆλ‹€.")

# 각 μš΄μ†‘ μˆ˜λ‹¨ 클래슀
class Truck(Transport):
def deliver(self):
return "νŠΈλŸ­μ„ 타고 μš΄λ°˜ν•œλ‹€"

class Ship(Transport):
def deliver(self):
return "λ°°λ₯Ό 타고 μš΄λ°˜ν•œλ‹€"

class Airplane(Transport):
def deliver(self):
return "λΉ„ν–‰κΈ°λ₯Ό 타고 μš΄λ°˜ν•œλ‹€"

# νŒ©ν† λ¦¬ 클래슀
class TransportFactory:
def create_transport(self, transport_type: TransportType):
if transport_type == TransportType.TRUCK:
return Truck()
elif transport_type == TransportType.SHIP:
return Ship()
elif transport_type == TransportType.AIRPLANE:
return Airplane()
else:
raise ValueError(f"μ•Œ 수 μ—†λŠ” μš΄μ†‘ μˆ˜λ‹¨: {transport_type}")

# μ‚¬μš© μ˜ˆμ‹œ
factory = TransportFactory()

transport1 = factory.create_transport(TransportType.TRUCK)
print(transport1.deliver()) # "νŠΈλŸ­μ„ 타고 μš΄λ°˜ν•œλ‹€"

transport2 = factory.create_transport(TransportType.AIRPLANE)
print(transport2.deliver()) # "λΉ„ν–‰κΈ°λ₯Ό 타고 μš΄λ°˜ν•œλ‹€"

4. νŒ©ν† λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄μ˜ μž₯점​

  1. μœ μ—°μ„± 증가: μƒˆλ‘œμš΄ μš΄μ†‘ μˆ˜λ‹¨μ„ μΆ”κ°€ν•  λ•Œ TransportTypeμ—λ§Œ μƒˆλ‘œμš΄ νƒ€μž…μ„ μ •μ˜ν•˜λ©΄ λ©λ‹ˆλ‹€.
  2. μ½”λ“œ 쀑볡 κ°μ†Œ: 객체 생성 μ½”λ“œκ°€ ν•œ 곳에 λͺ¨μ—¬ μžˆμ–΄ 쀑볡을 쀄이고 μœ μ§€λ³΄μˆ˜κ°€ μš©μ΄ν•©λ‹ˆλ‹€.
  3. ν™•μž₯μ„± ν–₯상: ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œκ°€ ꡬ체적인 ν΄λž˜μŠ€μ— μ˜μ‘΄ν•˜μ§€ μ•Šκ³ , μΈν„°νŽ˜μ΄μŠ€λ‚˜ 좔상 클래슀λ₯Ό 톡해 객체λ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  4. SOLID 원칙 μ€€μˆ˜: 개방-폐쇄 원칙(OCP)κ³Ό 단일 μ±…μž„ 원칙(SRP)을 λ§Œμ‘±ν•©λ‹ˆλ‹€.

5. κ°œμ„ λœ μ½”λ“œ μ˜ˆμ‹œ (λ§€ν•‘ ν…Œμ΄λΈ” ν™œμš©)​

쑰건문 λŒ€μ‹  λ§€ν•‘ ν…Œμ΄λΈ”μ„ ν™œμš©ν•˜μ—¬ 객체 생성을 λ”μš± κ°„λ‹¨ν•˜κ²Œ λ§Œλ“€ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

# νŒ©ν† λ¦¬ 클래슀 κ°œμ„ 
class TransportFactory:
transport_classes = {
TransportType.TRUCK: Truck,
TransportType.SHIP: Ship,
TransportType.AIRPLANE: Airplane
}

def create_transport(self, transport_type: TransportType):
transport_class = self.transport_classes.get(transport_type)
if transport_class is None:
raise ValueError(f"μ•Œ 수 μ—†λŠ” μš΄μ†‘ μˆ˜λ‹¨: {transport_type}")
return transport_class()

# μ‚¬μš© μ˜ˆμ‹œ
factory = TransportFactory()
transport = factory.create_transport(TransportType.TRUCK)
print(transport.deliver()) # "νŠΈλŸ­μ„ 타고 μš΄λ°˜ν•œλ‹€"

6. νŒ©ν† λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄μ˜ μ‹€μ œ μ‚¬μš© μ˜ˆβ€‹

  • λ°μ΄ν„°λ² μ΄μŠ€ 컀λ„₯μ…˜ ν’€: λ‹€μ–‘ν•œ λ°μ΄ν„°λ² μ΄μŠ€ λ“œλΌμ΄λ²„λ₯Ό μ„ νƒν•˜μ—¬ μ μ ˆν•œ 컀λ„₯μ…˜μ„ 생성할 수 있게 ν•΄μ€λ‹ˆλ‹€.
from enum import Enum, auto

class DBType(Enum):
MYSQL = "mysql"
POSTGRES = "postgres"

class DBConnection:
def connect(self):
pass

class MySQLConnection(DBConnection):
def connect(self):
return "MySQL μ—°κ²° 생성"

class PostgresConnection(DBConnection):
def connect(self):
return "Postgres μ—°κ²° 생성"

class DBConnectionFactory:
connection_classes = {
DBType.MYSQL: MySQLConnection,
DBType.POSTGRES: PostgresConnection
}

def create_connection(self, db_type: DBType):
connection_class = self.connection_classes.get(db_type)
if connection_class is None:
raise ValueError(f"μ•Œ 수 μ—†λŠ” λ°μ΄ν„°λ² μ΄μŠ€ μœ ν˜•: {db_type}")
return connection_class()

# μ‚¬μš© μ˜ˆμ‹œ
factory = DBConnectionFactory()
connection = factory.create_connection(DBType.MYSQL)
print(connection.connect()) # "MySQL μ—°κ²° 생성"

7. 결둠​

νŒ©ν† λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄μ€ μ½”λ“œμ˜ μœ μ§€λ³΄μˆ˜μ„±κ³Ό ν™•μž₯성을 높이고, 객체 생성에 λŒ€ν•œ μ±…μž„μ„ λΆ„λ¦¬ν•¨μœΌλ‘œμ¨ λ³΅μž‘ν•œ μ‹œμŠ€ν…œμ„ λ”μš± 효율적으둜 관리할 수 μžˆλ„λ‘ λ•μŠ΅λ‹ˆλ‹€. 특히 λ‹€μ–‘ν•œ ν΄λž˜μŠ€κ°€ 곡톡 κΈ°λŠ₯을 μ œκ³΅ν•΄μ•Ό ν•˜λŠ” κ²½μš°μ— μœ μš©ν•˜κ²Œ μ‚¬μš©λ  수 있으며, μ½”λ“œμ˜ μž¬μ‚¬μš©μ„±κ³Ό 가독성을 λ™μ‹œμ— 높일 수 μžˆμŠ΅λ‹ˆλ‹€.