한 객체가 수행해야 하는 범위. 책임에 맞게 설계.
ex) 사람은 운전의 책임이 있다. 차량은 감속/가속의 책임이 있다.
필요에 따라 의존하는 것. 객체 호출 등
class Car:
def __init__(self):
self.speed = 0
def accelerate(self):
self.speed += 10
def decelerate(self):
self.speed -= 10
class User:
def __init__(self) -> None:
self.car = MorningCar()
def drive(self) -> None:
self.car.accelerate()
class PorscheCar:
def __init__(self):
self.speed = 0
self._fuel = 0
def accelerate(self):
self.speed += 3
def decelerate(self):
self.speed -= 3
class User: # 다른 차 추가마다 elif 문 추가
def __init__(self, car_name: str) -> None:
if car_name == "morning":
self.car = MorningCar()
elif car_name == "porsche":
self.car = PorscheCar()
def drive(self):
self.car.accelerate()
from abc import ABC
class Car(ABC):
@abstractmethod
def accelerate(self) -> None:
spass
@abstractmethod
def decelerate(self) -> None:
pass
class PorscheCar(Car):
def __init__(self) -> None:
self.speed = 0
self._fuel = 0
def accelerate(self) -> None:
self.speed += 3
def decelerate(self) -> None:
self.speed -= 3
class MorningCar(Car):
def __init__(self) -> None:
self.speed = 0
self._fuel = 0
def accelerate(self) -> None:
self.speed += 1
def decelerate(self) -> None:
self.speed -= 1
class User:
def __init__(self, car: Car) -> None:
self.car = car
def drive(self):
self.car.accelerate()
user = User(MorningCar())
user.drive()
user = User(PorscheCar())
user.drive()
User는 생성자에서 추상 클래스인 Car를 의존하고 있음.
Car의 자식 클래스 객체를 파라미터로 넘겨 주고 있음.
OCP 준수
은닉 않고 직접 접근하는 것: SRP 위반, 검증되지 않은 값 들어가기 쉬움
!== Getter/Setter
캡슐화를 돕는 방법 중 하나일 뿐.
객체 내에서 다른 객체에 접근하는 경우.
User 객체가 Engineer 객체의 정보(속성, 메서드)를 아는 경우.
코드 레벨에서 드러나지는 않지만, 두 객체(인터페이스) 간 의존 관계
보통 추상클래스/인터페이스를 파라미터 타입으로 두고 의존성 주입으로 구체 클래스 객체를 인자로 넘겨주는 방식.
정적 의존성 대상을 고수준(인터페이스) 코드로,
동적 의존성 대상을 저수준(인스턴스) 코드로 하자.
SRP. 한 객체에 책임에 따른 기능이 충분히 모여있도록.
객체의 정적 의존성 정도.
한 객체가 다른 객체의 정보를 알수록 좋지 않음.
class GrabStore:
def __init__(self):
self.money = 0
self.name = "그랩마켓"
self.products = {
1: {"name": "키보드", "price": 30000},
2: {"name": "모니터", "price": 50000},
}
def set_money(self, money):
self.money = money
def set_products(self, products):
self.products = products
def get_money(self):
return self.money
def get_products(self):
return self.products
class User:
def __init__(self):
self.money = 0
self.store = GrabStore()
self.belongs = []
def set_money(self, money):
self.money = money
def set_belongs(self, belongs):
self.belongs = belongs
def get_money(self):
return self.money
def get_belongs(self):
return self.belongs
def get_store(self):
return self.store
def see_product(self, product_id):
products = self.store.get_products()
return products[product_id]
def purchase_product(self, product_id):
product = self.see_product(product_id)
if self.money >= product["price"]:
self.store.products.pop(product_id) # 상점에서 상품 꺼내기
self.money -= product["price"] # 사용자가 돈 내기
self.store.money += product["price"] # 상점에서 돈 받기
self.belongs.append(product)
return product
else:
raise Exception("잔돈이 부족합니다")
if __name__ == "__main__":
user = User()
user.set_money(100000)
user.purchase_product(product_id=1)