classUser:def__init__(self):self.money=0self.store=SixminiStore()self.belongs=[]defset_money(self,money):self.money=moneydefset_belongs(self,belongs):self.belongs=belongsdefget_money(self):returnself.moneydefget_belongs(self):returnself.belongsdefget_store(self):returnself.storedefsee_product(self,product_id):products=self.store.get_products()returnproducts[product_id]defpurchase_product(self,product_id):product=self.see_product(product_id)ifself.money>=product["price"]:self.store.products.pop(product_id)# 상점에서 상품 꺼내기
self.money-=product["price"]# 사용자가 돈 내기
self.store.money+=product["price"]# 상점에서 돈 받기
self.belongs.append(product)returnproductelse:raiseException("잔돈이 부족합니다")
# 1. 다른 Store가 들어오면 어떻게 될까?
# 개선점
# 1. Store를 추상화한다.
# 2. 의존성 주입을 한다
# 2. Store에 있는 상품과 돈을 마음대로 접근할 수 있다.
# 개선점
# 1. Store의 책임을 정의하고 캡슐화한다.
# 2. User의 결제 로직을 수정한다.
# 3. User도 캡슐화해보자!
# 3. User가 많은 행위를 책임지고 있다. Store가 판매하는 책임을 가져야 하지 않을까?
# 개선점
# 1. 상점에서 상품을 판매하는 행위를 추상화하고 구체적인 로직을 해당 메서드로 옮긴다.
# 4. product가 책임을 가져야 하지 않을까?
# 개선점
# 1. 딕셔너리 타입을 클래스(데이터클래스) 객체로 변환하자.
fromabcimportABC,abstractmethodfromdataclassesimportdataclass@dataclassclassProduct:name:strprice:intclassStore(ABC):@abstractmethoddef__init__(self):self._money=0self.name=""self._products={}@abstractmethoddefshow_product(self,product_id):pass@abstractmethoddefsell_product(self,product_id,money):passclassSixminiStore(Store):def__init__(self,products):self._money=0self.name="식스마켓"self._products=productsdefset_money(self,money:int):self._money=moneydefset_products(self,products):self._products=productsdefshow_product(self,product_id):returnself._products[product_id]defsell_product(self,product_id,money):# Validation 코드는 최소화
product=self.show_product(product_id=product_id)ifnotproduct:raiseException("상품이 존재하지 않는다")self._take_money(money=money)try:_product=self._take_out_product(product_id=product_id)return_productexceptExceptionase:self._return_money(money)raiseedef_take_out_product(self,product_id):returnself._products.pop(product_id)def_take_money(self,money):self._money+=moneydef_return_money(self,money):self._money-=moneyclassUser:def__init__(self,money,store:Store):self._money=moneyself.store=storeself.belongs=[]defget_money(self):returnself._moneydefget_belongs(self):returnself.belongsdefget_store(self):returnself.storedefsee_product(self,product_id):product=self.store.show_product(product_id=product_id)returnproductdefpurchase_product(self,product_id):product=self.see_product(product_id=product_id)price=product.priceifself._check_money_enough(price=price):self._give_money(money=price)try:my_product=self.store.sell_product(product_id=product_id,money=price)self._add_belong(my_product)returnmy_productexceptExceptionase:self._take_money(money=price)print(f"구매중 문제가 발생했습니다 {str(e)}")else:raiseException("잔돈이 부족합니다")def_check_money_enough(self,price):returnself._money>=pricedef_give_money(self,money):self._money-=moneydef_take_money(self,money):self._money+=moneydef_add_belong(self,product):self.belongs.append(product)# List에 값을 추가할 때 append 메서드를 사용
if__name__=="__main__":store=SixminiStore(products={1:Product(name="키보드",price=30000),2:Product(name="냉장고",price=500000)})user=User(money=100000,store=store)user.purchase_product(product_id=2)print(f"user의 잔돈 : {user.get_money()}")print(f"user가 구매한 상품 : {user.get_belongs()}")