패턴 태그
[퍼사드 패턴]
패턴 설명
퍼사드 패턴은 서브시스템에 있는 인터페이스들에 대한 통합된 인터페이스를 제공한다. 퍼사드란 서브시스템을 더 쉽게 사용할 수 있도록 만드는 더 높은 수준의 인터페이스를 말한다.
[예시]
간단한 예시로 자동차를 들 수 있다. 자동차의 구성요소를 생각해보자. 자동차라는 물질은 대략 엔진, 파워 트레인, 차축, 휠 어셈블리, 전자 장치, 조향 시스템, 브레이크 시스템, ETC.. 즉, 여러가지 기계장치들로 구성되어 있다. 이걸 프로그래밍적 표현으론 다른 컴포넌트들로 구성되어 있다고도 표현할 수 있다.
즉, 퍼사드 패턴은 프로그램을 구성할때 큰 프로젝트를 다양한 기능들로 쪼개고 쪼개서 각각의 기능들을 구현하고, 구현된 하나하나의 기능들을 최종적으로 합해, 하나의 큰 프로젝트로 만드는것을 의미한다.
간단한 예시로 자동차로 들었지만, 이 외에도 실생활에서 만지는 거의 대부분은 퍼사드라고 봐도 무방하다. 가령 컴퓨터 또한 서로 다른 일을 처리하는 각각의 장치들이 모여 컴퓨터를 이루고, 산업용 로봇 또한 이와 비슷하다.
퍼사드 패턴을 이해했으면 위의 설명한 간단한 예시[자동차]로 퍼사드 패턴을 구현해보자.
예시를 위해서 자동차, 브레이크, 엔진, 프레임(자동차 프레임), 서스펜션, 트렌스미션, 휠, 휠어셈블리 클래스를 만들고 마지막에 자동차 클래스에서 한번에 취합하여 동작하도록 만들었다.
# Brake.py
class Brake(object):
"""
* 자동차 브레이크 클래스를 정의한다.
"""
def __init__(self, number, type='disc') -> None:
self.type = type
self.number = number
def engage(self):
"""
* 브레이크 작동!
"""
print(f'{self.__class__.__name__}, {self.number} engaged')
def release(self):
"""
* 브레이크 풀기
"""
print(f'{self.__class__.__name__}, {self.number} release')
# Engine.py
class Engine(object):
"""
* 자동차 엔진 클래스를 정의한다.
"""
def __init__(self, name, bhp, rpm, volume, cylinders=4, type='petrol') -> None:
self.name = name
self.bhp = bhp
self.rpm = rpm
self.volume = volume
self.cylinders = cylinders
self.type = type
def start(self):
"""
* 엔진 스타트!
"""
print('Engine Start')
def stop(self):
"""
* 엔진 멈춤
"""
print('Engine Stop')
# Frame.py
class Frame(object):
"""
* 자동차 프레임 클래스를 정의한다.
"""
def __init__(self, length, width) -> None:
self.length = length
self.width = width
# Suspension.py
class Suspension(object):
"""
* 자동차 서스펜션 클래스를 정의한다.
"""
def __init__(self, load, type='mcpherson') -> None:
self.type = type
self.load = load
# Transmission.py
class Transmission(object):
"""
* 자동차 트랜스미션 클래스를 정의한다.
"""
def __init__(self, gear, torque) -> None:
self.gear = gear
self.torque = torque
self.gear_pos = 0
def shift_up(self):
"""
* 기어 업!
"""
if self.gear_pos == self.gear:
print('기어를 올릴 수 없습니다.')
else:
self.gear_pos += 1
print(f'Shift up to gear -> {self.gear_pos}')
def shift_down(self):
"""
* 기어 다운!
"""
if self.gear_pos == -1:
print('후진 상태입니다. 더 기어를 내릴 수 없습니다.')
else:
self.gear_pos -= 1
print(f'Shifted down to gear -> {self.gear_pos}')
def shift_reverse(self):
"""
* 후진
"""
print('후진')
self.gear_pos = -1
def shift_to(self, gear):
"""
* 기어를 변동합니다.
"""
self.gear_pos = gear
print(f'현재 기어를 {self.gear_pos}로 변동합니다.')
# Wheel.py
class Wheel(object):
"""
* 자동차 휠 클래스를 정의한다.
"""
def __init__(self, material, diameter, pitch) -> None:
self.material = material
self.diameter = diameter
self.pitch = pitch
# WheelAssembly.py
# 휠 클래스 인포트!
from .Wheel import Wheel
class WheelAssembly(object):
"""
* 자동차 휠 어셈블리 클래스를 정의한다.
"""
def __init__(self, brake, suspension) -> None:
self.brake = brake
self.suspension = suspension
self.wheels = Wheel(material='합금', diameter='M12', pitch=1.25)
def apply_brakes(self):
"""
* 브래이크 적용
"""
print('Applying brakes')
self.brake.engage
# Car.py
from Architecture.Facade.Brake import Brake
from Architecture.Facade.Engine import Engine
from Architecture.Facade.Frame import Frame
from Architecture.Facade.Suspension import Suspension
from Architecture.Facade.Transmission import Transmission
from Architecture.Facade.WheelAssembly import WheelAssembly
class Car(object):
"""
* 자동차 구성 - 퍼사드 패턴
"""
def __init__(self, model, manufacturer) -> None:
self.engine = Engine('BMW 330e', 85, 5000, 1.3)
self.frame = Frame(385, 170)
self.wheel_assemblies = []
for i in range(4):
self.wheel_assemblies.append(WheelAssembly(Brake(i+1), Suspension(1000)))
self.transmission = Transmission(5, 115)
self.model = model
self.manufacturer = manufacturer
# 점화 장치
self.ignition = False
def start(self):
"""
* 시동 ON
"""
print('자동차 운행 시작')
# 점화 장치
self.ignition = True
# self.park_brake.release()
self.engine.start()
self.transmission.shift_up()
print('시동이 걸렸습니다.')
def stop(self):
print('운행을 종료합니다.')
# 감속
for wheel_a in self.wheel_assemblies:
wheel_a.apply_brakes()
# Move to 2nd gear and then 1st
self.transmission.shift_to(2)
self.transmission.shift_to(1)
self.engine.stop()
# shift to neutral
self.transmission.shift_to(0)
# Engage parking brake
print('자동차 운행종료 완료')
if __name__ == '__main__':
car = Car('람보르기니', '이탈리아')
print(car)
print(car.start())
print(car.stop())
이렇게 우리는 각각의 필요한 부품(클래스)를 생성하고, 마지막에 Car라는 클래스에서 취합하면서 자동차를 생성했다.
이제 Car클래스의 인스터를 생성해서 실행해보자!
하단은 car.start()에 대한 결과값이다.

이번엔 car.stop()에 대한 결과값이다.

이렇게 예시를 통해서 알 수 있듯 퍼사드를 사용하여, 각각의 컴포넌트별로 구성하고, 하나의 프로젝트를 생산할 시 얻는 이점은! => 시스템의 복잡성을 제거하는데 유용하다는 점이다.
따라서 시스템의 작업 수행을 쉽게 만든다. 위의 예시에서 start와 stop 메소드를 만들지 않았다면, 작업은 매우 복잡했을 것이다. 그러나 우리가 Start와 Stop 메소드에 서브시스템 배경작업을 숨겼기 때문에 복잡성을 줄일 수 있었다.
위의 예제에서는 Car 클래스 내부에서 start와 stop을 시켰지만 실제로 사용한다면, 내가 필요로 하는 클래스 혹 프로젝트 내부에서 Car 클래스의 start, stop만을 활용하여 모든 클래스들을 사용할 수 있게 되는것이다.
'프로그래밍 > 아키텍처 with python' 카테고리의 다른 글
[Architecture][Python]상속과 서브 클래스 (1) | 2022.05.24 |
---|---|
[Architecture][Python]프록시 패턴 (0) | 2022.03.29 |