1. Customer 클래스
이 클래스는 고객의 기본 정보를 저장하는 추상 클래스 이다.
abstract class Customer {
private String cname;
private String city;
private int age;
// 생성자
public Customer(String cname, String city, int age) {
this.cname = cname;
this.city = city;
this.age = age;
}
public abstract double applyDiscount(double totalAmount);
public String getCname() { return cname; }
public void setCname(String cname) { this.cname = cname; }
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override
public String toString() {
return "Name: " + cname + ", City: " + city + ", Age: " + age;
}
}
- 필드 : cname, city, age는 고객의 이름, 도시, 나이를 저장한다.
- 생성자 : 고객의 기본 정보를 초기화한다.
- 추상메서드 : applyDiscount()는 실제 할인 로직을 구현하는 서브클래스에서 정의해야 한다.
( RegularCustomer class / PremiumCustomer class)
- Getter / Setter : 필드에 접근하고 값을 설정하는 메서드
- toString 메서드 : 고객의 정보를 문자열로 반환
💡private 접근 제어자 사용 이유 :
- 클래스 내부의 데이터(멤버 변수)를 외부에서 접근하지 못하게 하여 데이터의 무결성을 보호한다. 데이터는 메서드를 통해서만 접근할 수 있도록 하여 객체의 상태를 안전하게 관리할 수 있다.
💡 this 키워드 :
- this는 현재 객체를 참조하는 키워드. 생성자에서 매개변수와 멤버 변수의 이름이 동일할 때 this를 사용하여 멤버 변수를 명확하게 구분한다. this.cname=cname; 은 현재 객체의 cname 속성에 생성자 매개변수로 전달된 cname 값을 할당한다.
💡 추상 클래스 :
- Customer 클래스는 applyDiscount라는 추상 메서드를 정의하여, 구체적인 고객 클래스에서 할인 정책을 정의할 수 있도록 한다. 추상 클래스는 공통 속성과 메서드를 정의하면서, 서브 클래스에서 구체적인 구현을 제공하도록 강제한다.
2. RegularCustomer 클래스 (일반 고객 클래스 )
- Customer 클래스를 상속받아 일반 고객을 구현한다.
package classTest3;
import classTest3.Customer;
public class RegularCustomer extends Customer {
static final double REGULARDISCOUNT_RATE = 0.03; //3% 할인
public RegularCustomer(String cname, String city, int age) {
super(cname, city, age);
}
public double applyDiscount(double totalAmount) {
return totalAmount; //일반 고객은 할인 x
}
}
- 생성자 : 부모 클래스(Customer)의 생성자를 호출하여 고객의 정보를 초기화한다.
- applyDiscount 메서드 : 일반 고객은 추가 할인이 없으므로, 전달된 금액을 그대로 반환한다.
3. PremiumCustomer 클래스
Customer 클래스를 상속받아 프리미엄 고객을 구현한다.
package classTest3;
import classTest3.Customer;
public class PremiumCustomer extends Customer {
static final double DISCOUNT_RATE = 0.1; //10% 할인
public PremiumCustomer(String cname, String city, int age) {
super(cname, city, age);
}
public double applyDiscount(double totalAmount) {
return totalAmount * ( 1 - DISCOUNT_RATE);
}
}
- 생성자 : 부모 클래스(Customer)의 생성자를 호출하여 고객 정보를 초기화한다.
- applyDiscount 메서드 : 프리미엄 고객은 10% 할인을 적용한다.
4. Discountable 인터페이스
- 할인 정책을 정의하는 인터페이스
interface Discountable{
double getDiscountedPrice(double price);
}
- getDiscountedPrice 메서드 : 가격에 할인 정책을 적용한 후의 가격을 반환한다.
💡 인터페이스 :
- 인터페이스는 구현 클래스를 정의하지 않고 메서드의 시그니처만 정의한다. 이를 통해 다양한 클래스에서 공통적으로 사용할 수 있는 메서드를 정의하고, 다양한 할인 정책을 구현할 수 있다.
5.SeconalDiscount 클래스
- Discountable 인터페이스를 구현하여 시즌 할인을 적용한다.
package classTest3;
import classTest3.Discountable;
public class SeasonalDiscount implements Discountable {
private double discountRate;
public SeasonalDiscount(double discountRate) {
this.discountRate = discountRate;
}
@Override
public double getDiscountedPrice(double price) {
return price * (1 - discountRate);
}
}
- 생성자 : 할인 비율을 설정한다.
- getDiscountedPrice 메서드 : 전달된 가격에 할인 비율을 적용한 후의 가격을 반환한다.
💡 생성자 :
- SeconalDiscount 클래스의 생성자는 할인율을 초기화한다. 할인율은 클래스의 속성으로 저장하여 getrDiscountedPrice 메서드에서 사용할 수 있도록 한다.
💡 메서드 구현 :
- getDiscountedPrice 메서드는 Discountable 인터페이스에서 정의된 메서드를 구현하며, 주어진 가격에 할인율을 적용하여 할인된 가격을 반환한다.
6. Item 클래스
- 제품의 기본 정보를 저장하는 추상 클래스이다.
abstract class Item {
private String name;
private double price;
private int stockQuantity;
public Item(String name, double price, int stockQuantity) {
this.name = name;
this.price = price;
this.stockQuantity = stockQuantity;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public int getStockQuantity() {
return stockQuantity;
}
public void setStockQuantity(int stockQuantity) {
this.stockQuantity = stockQuantity;
}
}
- 필드 : name, price, stockQuantity는 제품의 이름, 가격, 재고량을 저장한다.
- 생성자 : 제품의 기본 정보를 초기화한다.
- Getter/Setter : 필드에 접근하고 값을 설정하는 메서드이다.
7. Electronics 클래스 / Clothing 클래스
- Item 클래스를 상속받아 전자 제품 / 의류 제품을 구현한다.
class Electronics extends Item {
private int madeYear;
public Electronics(String name, double price, int stockQuantity, int madeYear) {
super(name, price, stockQuantity);
this.madeYear = madeYear;
}
public int getMadeYear() {
return madeYear;
}
}
class Clothing extends Item {
private int size;
public Clothing(String name, double price, int stockQuantity, int size) {
super(name, price, stockQuantity);
this.size = size;
}
public int getSize() {
return size;
}
}
Electronic 클래스
- 필드 : nadeYear는 제품의 제조 연도를 저장한다.
- 생성자 : Item의 기본 정보와 madeYear를 초기화한다.
- Getter : madeYear의 값을 반환한다.
Clothing 클래스
- 필드 : size는 의류의 사이즈를 저장한다.
- 생성자 : Item의기본 정보와 사이즈를 초기화한다.
- Getter : size의 값을 반환한다.
💡 상속 :
- Electronics와 Clothing은 Item의 특수화된 버전으로, 기본적인 제품 정보를 공유하며 각각의 고유한 속성을 추가한다. 이를 통해 코드의 재사용성을 높이고, 공통적인 기능을 상속받아 사용한다.
8. Order 클래스
- 주문을 처리하고, 요약 및 할인 내역을 출력하는 클래스이다.
class Order {
private static final int N = 20;
private Customer customer;
private Item[] items;
private int[] quantities;
private String[] orderDates;
private int itemCount;
private Discountable discountPolicy;
public Order(Customer customer, Discountable discountPolicy) {
this.customer = customer;
this.items = new Item[N];
this.quantities = new int[N];
this.orderDates = new String[N];
this.itemCount = 0;
this.discountPolicy = discountPolicy;
}
public void addItem(Item item, int quantity, String date) {
if (itemCount < N) {
items[itemCount] = item;
quantities[itemCount] = quantity;
orderDates[itemCount] = date;
itemCount++;
if(item.getStockQuantity() >= quantity) {
item.setStockQuantity(item.getStockQuantity()-quantity);
}else {
System.out.println("재고 부족 : " + item.getName());
itemCount--;
}
}
}
public double calculateTotal() {
double total = 0;
for (int i = 0; i < itemCount; i++) {
total += items[i].getPrice() * quantities[i];
}
return total;
}
public void printOrderSummary() {
System.out.println("고객: " + customer.getCname());
System.out.println("주문요약:");
for (int i = 0; i < itemCount; i++) {
System.out.println("- " + items[i].getName() + " x " + quantities[i] + ": W" + (items[i].getPrice() * quantities[i]));
}
}
public void printDiscountDetails() {
double total = calculateTotal();
double discountedTotal = discountPolicy.getDiscountedPrice(total);
double finalTotal = customer.applyDiscount(discountedTotal);
System.out.println("할인 내역:");
for (int i = 0; i < itemCount; i++) {
double originalPrice = items[i].getPrice();
double seasonDiscount = originalPrice - discountPolicy.getDiscountedPrice(originalPrice);
double customerDiscount = discountedTotal - customer.applyDiscount(discountedTotal);
double discountedPrice = originalPrice - seasonDiscount - customerDiscount;
System.out.println("- " + items[i].getName() + ": 원래 가격 W" + originalPrice + ", 시즌할인금액 W" + seasonDiscount + ", 고객할인금액 W" + customerDiscount + ", 할인 후 가격 W" + discountedPrice);
}
System.out.println("할인되어 지불해야 하는 금액 = " + finalTotal);
System.out.println("------------------------------------------------------------------------------------------------");
}
}
- 필드 : customer(주문을 하는 고객 객체), items(주문에 포함된 아이템 배열), quantities(각 아이템의 수량 배열), - - - - orderDates(주문 날짜 배열), itemCount(현재 주문에 추가된 아이템 수), discountPolicy(적용할 할인 정책)
- 생성자 : 고객과 할인 정책을 받아서 초기화한다.
- addItem 메서드 : 아이템과 수량, 날짜를 주문에 추가한다. 배열의 최대 크기인 N을 초화하지 않도록한다.
- calculateTotal 메서드 : 전체 주문의 금액을 계산한다.
- printOrderSummary 메서드 : 주문 요약 출력
- printDiscountDetails 메서드 : 할인 내역을 계산하고 출력. 시즌 할인과 할인을 적용하여 최종 금액을 계산한다.
9. ExamB4 클래스
- 애플리케이션의 메인 클래스
public class ExamB3 {
static void showItemsStock(Item[] items) {
for (Item item : items) {
if (item != null) {
System.out.println(item.getName() + " - Stock: " + item.getStockQuantity() + " - Price: " + item.getPrice());
}
}
}
public static void main(String[] args) {
Item[] items = new Item[4];
items[0] = new Electronics("노트북", 1500, 50, 2023);
items[1] = new Clothing("티셔츠", 50, 1500, 95);
items[2] = new Electronics("휴대폰", 800, 100, 2024);
items[3] = new Clothing("청바지", 80, 100, 90);
// 모든 아이템의 이름,재고량,가격 출력
showItemsStock(items);
// 고객 생성
Customer regularCustomer = new RegularCustomer("홍길동", "서울", 30);
Customer premiumCustomer = new PremiumCustomer("강감찬", "부산", 45);
// 주문 생성 및 계산 (RegularCustomer)
Order regularOrder = new Order(regularCustomer, new SeasonalDiscount(0.20)); // 20% seasonal discount
regularOrder.addItem(items[0], 1, "240901");
regularOrder.addItem(items[1], 2, "240902");
regularOrder.printOrderSummary();
regularOrder.printDiscountDetails(); // 할인된 내역 출력
// 주문 생성 및 계산 (PremiumCustomer)
Order premiumOrder = new Order(premiumCustomer, new SeasonalDiscount(0.20)); // 20% seasonal discount
premiumOrder.addItem(items[1], 1, "240901");
premiumOrder.addItem(items[3], 2, "240903");
premiumOrder.printOrderSummary();
premiumOrder.printDiscountDetails(); // 할인된 내역 출력
// 모든 아이템의 이름과 재고량, 가격 출력
showItemsStock(items);
}
}
- showItemsStock 메서드 : Item 배열의 아이템 이름, 재고량, 가격을 출력한다.
- main메서드 :
- 아이템 배열 생성 : 전자 제품과 의류 제품을 배열에 추가한다.
- 아이템 정보 출력 : 모든 아이템의 정보를 출력한다.
- 고객 생성 : RegularCustomer와 PremiumCustomer 객체를 생성한다.
- 주문 생성 및 계산 : 각 고객에 대한 order 객체를 생성하고, 아이템을 추가한 후 주문 요약 및 할인 내역을 출력한다.
- 아이템 정보 출력 : 모든 아이템의 정보를 다시 출력한다.
결과
*** 추가로 고객 할인 금액/ 할인 후 가격에 반올림 적용하기 !
'Backend > Java' 카테고리의 다른 글
[Java] 기본형 매개변수와 참조형 매개변수 (0) | 2024.09.09 |
---|---|
[Java] JVM 메모리 구조 / JVM 수행 과정 (1) | 2024.09.05 |
[Java] Class 변수와 메서드 (0) | 2024.09.02 |
[Java] Class 객체 배열 (0) | 2024.08.30 |
[Java] Class 란 / 인스턴스란 / 인스턴스의 생성과 사용 (0) | 2024.08.29 |