My Melody Is Cute BurgerQueen 주문 프로그램 만들기 4
본문 바로가기

실습👁️‍🗨️/연습

BurgerQueen 주문 프로그램 만들기 4

🌼복사생성자 적용을 통한 문제 해결

장바구니에 상품을 담을때 객체를 생성해서 담는 것이 아니라

객체의 참조값을 장바구니에 그대로 담게 된다

동일한 상품을 두 번 고르면서 옵션은 다르게 고르는 경우에 문제가 발생하는데 

마지막으로 추가한 옵션 항목으로 덮어쓰이게 된다

옵션값이 마지막에 추가한 값과 동일해졌다

addToCart()에 새로운 상품객체를 생성하여 items에 담을 수 있도록 코드를 수정해야한다

얕은 복사  = 객체의 참조값을 복사하는 것

public void shallowCopyExample(Product product) {
	Product newProduct = product; //객체가 위치한 힙메모리 주소값 동일한 객체를 가리킴
}

 

깊은 복사 = 내용이 동일하지만 참조값이 다른 새로운 객체를 생성하는것을 의미

public void DeepCopyExample(Product product) {
	Product newProduct = new Product(product.getId, product.getName, ...);
}

 

새로운 객체를 만들도록 해야한다 먼저 Hambuger,Side,Drink 생성자를 오버로딩해서 추가해준다

addToCart()에서 새로운 객체를 생성해서 items에 추가하도록 해준다

composeSet()에서도 새로운 Side,Drink 인스턴스를 만들도록 수정

 

옵션값이 각각 저장이 잘 된다

 

🌼주문 기능 구현

 

주문은 장바구니에 담긴 상품을 기반으로 이루어짐

cart객체를 통째로 정의

(할인코드는 나중에 추가)

makeOrder()

장바구니의 상품을 주문하는 기능 주문내역 출력

입력값 : items에 있는 상품을 단순하게 출력하는거라 필요x

반환값 : 출력이라 필요 x

접근제어자 : OrderApp에서 호출해야해서 public

public void makeOrder() {

    System.out.println("[📣] 주문이 완료되었습니다. ");
    System.out.println("[📣] 주문 내역은 다음과 같습니다. ");
    System.out.println("-".repeat(60));

    상품 상세 내역 출력

    System.out.println("-".repeat(60));
    System.out.printf("금액 합계      : %d원\n", 금액 합계 계산);
}

상세 내역 - cart.printCartItemDetails() / 금액합계 - cart.calculateTotalPrice()

접근범위를 private로 해둔것을 public이나 protected로 변경

OrderApp에 출력코드를 추가하고 테스트 해보기

주문내역이 잘 나온다

 

🌼할인기능 구현

 

- 코드스테이츠 수강생에게 10% 할인 = 고정비율 할인 구현

- 20세 미만 청소년에게 500원 할인 = 고정금액 할인 구현

할인 정책

- 특정 할인조건에 부합하는 경우 ( 두가지 조건 모두 구현 )

할인 조건

- 상시 또는 불특정한 할인 이벤트 ( 변화에 유연한 대응 객체지향원리 )

객체지향적인 설계

 

할인정책 - 고정비율 할인 : FixedRateDiscoutPolicy 클래스

- 고정금액 할인 : FixedAmountDiscountPolicy  클래스

할인 조건 - 코드스테이츠 수강생 할인 : CozDiscountCondition 클래스

- 청소년 할인 : KidDiscountCondition 클래스

객체지향적인 설계 - 객체지향적이지 않은 코드를 설계후 변화와 확장에 유리하도록 리팩토링 해보기

-> 단점 파악해보기 / 리팩토링 후 장점 파악해보기

 

🌼할인 정책 구현

 

고정비율할인 FixedRateDiscountPolicy

 

고정금액할인 FixedAmountDiscountPolicy

 

 

 

🌼할인 조건 구현

 

1. 할인 조건 검사 : 할인 조건에 부합하는지 검사하고 부합여부 저장

2. 할인 정책 결정 : 할인 조건에 따라 적용할 할인 정책 지정

 

- 조건마다 검사 메서드가 필요 = checkDiscountCondition() 메서드

- 조건 검사의 결과를 저장 = isSatisfied 필드

- 조건에 부합하면 어떤 정책을 적용시킬지 지정 = fixedRateDiscountPolicy / fixedAmountDiscountPolicy 필드

- 할인 적용한 가격을 계산해서 사용자에게 보여줌  = applyDiscount() 메서드

 

CozDiscountCondition

코드스테이츠 수강생할인조건

checkDiscountCondition() & isSatisfied

조건에 부합하는지 물어보는 문장 출력

입력한 값의 부합여부를 isSatisfied의 값으로 저장

 

fixedRateDiscountPolicy

할인 정책은 할인조건에 따라 어떻게 할인을 해줄지 방법에 관한것

코드스테이츠 수강생 -> 고정비율 할인

청소년 -> 고정금액 할인

할인 정책은 할인 조건을 구현하는 클래스에 필드로 정의 되어야 한다

applyDiscount()

할인정책을 적용해서 실제할인 금액을 리턴해주는 메서드

calculateDiscountedPrice()의 결과값을 그대로 리턴

 

KidDiscountCondition

청소년할인조건

 

 

🌼할인 기능 적용

주문하기 눌렀을때 적용이 되는 기능

Order에서 조건을 묻고 할인을 적용해주는 메서드 호출

checkDiscountCondition() / applyDiscount()

 

 

🌼문제점 분석

변화와 확장에 취약

코드간 결합도가 높아 요구사항이 변경 되었을때

수정해주어야할 코드가 상대적으로 많다

할인 조건에 따른 할인정책이 바뀐다면??

1. 코드스테이츠 수강생에게 고정금액할인을 , 청소년에게 고정비율 할인을 적용하도록 바뀐다면 여러군데를 수정해주어야한다.

public class CozDiscountCondition {

    ...

    // 기존 코드 : private FixedRateDiscountPolicy fixedRateDiscountPolicy = new FixedRateDiscountPolicy(10);
		
    // 변경된 코드 (예시일 뿐이니, 진짜로 변경하지는 마세요!)
    private FixedAmountDiscountPolicy fixedAmountDiscountPolicy = new FixedAmountDiscountPolicy(500);

    ...

    public int applyDiscount(int price) {
        // 기존 코드 : return fixedRateDiscountPolicy.calculateDiscountedPrice(price);

        // 변경된 코드 (예시일 뿐이니, 진짜로 변경하지는 마세요!)
        return fixedAmountDiscountPolicy.calculateDiscountedPrice(price);
    }
}

public class KidDiscountCondition {

    ...

    // 기존 코드 : private FixedAmountDiscountPolicy fixedAmountDiscountPolicy = new FixedAmountDiscountPolicy(500);

    // 변경된 코드 (예시일 뿐이니, 진짜로 변경하지는 마세요!)
    private FixedRateDiscountPolicy fixedRateDiscountPolicy = new FixedRateDiscountPolicy(10);

    ...

    public int applyDiscount(int price) {
        // 기존 코드 : return fixedAmountDiscountPolicy.calculateDiscountedPrice(price);

        // 변경된 코드 (예시일 뿐이니, 진짜로 변경하지는 마세요!)
        return fixedRateDiscountPolicy.calculateDiscountedPrice(price);
    }
}

2. 새로운 할인 이벤트를 여는 경우

백엔드 수료생대상으로 할인이벤트를 연다면?

-CozBackEndDiscountCondition 클래스 정의

- Order에서 인스턴스생성하는 코드 추가 / checkDiscountCondition()을 호출하는 코드 추가 / applyDiscount()를 호출하는 코드 추가

클래스 정의는 필연적이지만

할인조건을 추가했을뿐인데 주문과 관련된 Order에 코드추가해야하는것은 기존 코드에 영향을 준다

public void makeOrder() {

    CozDiscountCondition cozDiscountCondition = new CozDiscountCondition();
    KidDiscountCondition kidDiscountCondition = new KidDiscountCondition();
				
    // 아래 코드를 추가해야 합니다. (예시일 뿐이니 진짜로 추가하지는 마세요)
    CozBackEndDiscountCondition cozBackEndDiscountCondition = new CozBackEndDiscountCondition();
        
    cozDiscountCondition.checkDiscountCondition();
    kidDiscountCondition.checkDiscountCondition();

    // 아래 코드를 추가해야 합니다. (예시일 뿐이니 진짜로 추가하지는 마세요)
    cozBackEndDiscountCondition.checkDiscountCondition();

    int totalPrice = cart.calculateTotalPrice();
        
    int finalPrice = totalPrice;

    if (cozDiscountCondition.isSatisfied()) finalPrice = cozDiscountCondition.applyDiscount(finalPrice);
    if (kidDiscountCondition.isSatisfied()) finalPrice = kidDiscountCondition.applyDiscount(finalPrice);
	
    // 아래 코드를 추가해야 합니다. (예시일 뿐이니 진짜로 추가하지는 마세요)
    if (cozBackEndDiscountCondition.isSatisfied()) finalPrice = cozBackEndDiscountCondition.applyDiscount(finalPrice);

    System.out.println("[📣] 주문이 완료되었습니다. ");
    System.out.println("[📣] 주문 내역은 다음과 같습니다. ");
    System.out.println("-".repeat(60));

    cart.printCartItemDetails();

    System.out.println("-".repeat(60));
    System.out.printf("금액 합계      : %d원\n", totalPrice);
    System.out.printf("할인 적용 금액 : %d원\n", finalPrice); // 추가