Java/JAVA 3 - 유용한 클래스

OOP 회원과 주문 관리 설계

CNOW 2024. 12. 19. 16:46

요약

  • 의존성 주입을 통해 객체 간의 결합도를 낮춥니다.
  • 싱글톤 패턴을 사용하여 인스턴스를 공유합니다.
  • 관심사 분리를 통해 설정과 비즈니스 로직을 분리하여 코드의 유지보수성을 높입니다.
  • AppConfig를 통해 필요한 객체를 주입 받습니다.

오늘은 객체 지향 설계를 할 수 있도록 연습해보는 코드를 작성해보겠습니다.

회원 가입 시스템 설계
package member;

public enum Grade {
	BASIC, VIP
}
package member;

public class Member {

	private Long id;
	private String name;
	private Grade grade;

	public Member(Long id, String name, Grade grade) {
		this.id = id;
		this.name = name;
		this.grade = grade;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Grade getGrade() {
		return grade;
	}

	public void setGrade(Grade grade) {
		this.grade = grade;
	}


}

 

Repository
package member.repository;

import member.Member;

public interface MemberRepsitory {

	void save(Member member);
	Member findById(Long memberId);
}
package member.repository;

import member.Grade;
import member.Member;

import java.util.HashMap;
import java.util.Map;

public class MemoryMemberRepositoryImpl implements MemberRepository {

    private static MemoryMemberRepositoryImpl instance;
    private Map<Long, Member> memberStore;

    private MemoryMemberRepositoryImpl() {
        memberStore = new HashMap<Long, Member>();
        initData();
    }

    @Override
    public void save(Member member) {
        memberStore.put(member.getId(), member);
    }

    @Override
    public Member findById(Long id) {
        return memberStore.get(id);
    }

    public static MemoryMemberRepositoryImpl getInstance() {
        if (instance == null) {
            instance = new MemoryMemberRepositoryImpl();
        }
        return instance;
    }

// 샘플 초기 데이터private void initData() {
        memberStore.put(1L, new Member(1L, "홍길동", Grade.VIP));
        memberStore.put(2L, new Member(2L, "성춘향", Grade.VIP));
        memberStore.put(3L, new Member(3L, "이몽룡", Grade.BASIC));
    }
}
package member.repository;

import member.Member;

public class DBMemberRepositoryImpl implements MemberRepository {



    @Override
    public void save(Member member) {

    }

    @Override
    public Member findById(Long id) {
        return null;
    }
}

 

Service
package member.service;

import member.Member;

public interface MemberService {

    void signUp(Member member);

    Member findByIdMember(Long memberId);

}
package member.service;

import member.Member;
import member.repository.MemberRepository;

public class MemberServiceImpl implements MemberService {

    private MemberRepository repository;

// 생성자 의존 주입public MemberServiceImpl(MemberRepository repository) {
        this.repository = repository;
    }

    @Override
    public void signUp(Member member) {
        repository.save(member);
    }

    @Override
    public Member findByIdMember(Long memberId) {
        return repository.findById(memberId);
    }
}

 

Main Class
package member;

import member.repository.MemberRepository;
import member.repository.MemoryMemberRepositoryImpl;
import member.service.MemberService;
import member.service.MemberServiceImpl;

public class MainTest1 {

    public static void main(String[] args) {

        MemberRepository memberRepository = MemoryMemberRepositoryImpl.getInstance();

        MemberService memberService = new MemberServiceImpl(memberRepository);

// 클라이언트
        Member member = new Member(100L, "티모", Grade.VIP);

// 신규 회원가입
        memberService.signUp(member);

        System.out.println(memberService.findByIdMember(100L).toString());
        System.out.println(memberService.findByIdMember(1L).toString());
        System.out.println(memberService.findByIdMember(2L).toString());
        System.out.println(memberService.findByIdMember(3L).toString());
    }

}

 

심화 - 할인율
package order;

import member.Member;

public interface DiscountPolicy {

    int discount(Member member, int price);

}

 

고정 할인율
package order;

import member.Grade;
import member.Member;

public class FixDiscountPolicyImpl implements DiscountPolicy {

    private int discountFixAmount = 1500;

    @Override
    public int discount(Member member, int price) {
// VIP 회원만 할인 금액 적용 된다.if(member.getGrade() == Grade.VIP) {
            return discountFixAmount;
        }
        return 0;
    }

}

 

변동 할인율 
package order;

import member.Grade;
import member.Member;

public class PercentDiscountPolicyImpl implements DiscountPolicy {

    private double discountPercent = 10.0;

    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP) {
            return (int)(price * (discountPercent / 100));
        }
        return 0;
    }

}

 

객체
package order;

public class Order {

    private Long memberId;
    private String itemName;
    private int itemPrice;
    private int discountPrice;

    public Order (Long memberId, String itemName, int itemPrice, int discountPrice) {
        this.memberId = memberId;
        this.itemName = itemName;
        this.itemPrice = itemPrice;
        this.discountPrice = discountPrice;
    }

// 상품 금액에 할인된 가격 금액 출력 하는 기능public int calculateDiscount() {
        return itemPrice - discountPrice;
    }

    public Long getMemberId() {
        return memberId;
    }

    public void setMemberId(Long memberId) {
        this.memberId = memberId;
    }

    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public int getItemPrice() {
        return itemPrice;
    }

    public void setItemPrice(int itemPrice) {
        this.itemPrice = itemPrice;
    }

    public int getDiscountPrice() {
        return discountPrice;
    }

    public void setDiscountPrice(int discountPrice) {
        this.discountPrice = discountPrice;
    }

    @Override
    public String toString() {
        return "Order{" +
                "memberId=" + memberId +
                ", itemName='" + itemName + '\'' +
                ", itemPrice=" + itemPrice +
                ", discountPrice=" + discountPrice +
                '}';
    }
}

 

서비스
package order;

public interface OrderService {
    Order createOrder(Long memberId, String itemName, int itemPrice);
}

 

서비스 구현체
package order;

import member.Member;
import member.repository.MemberRepository;

public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }

    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);
        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

 

Main Class
package order;

import member.Grade;
import member.Member;
import member.repository.MemberRepository;
import member.repository.MemoryMemberRepositoryImpl;

public class OrderServiceTest {

    public static void main(String[] args) {

        MemberRepository memberRepository = MemoryMemberRepositoryImpl.getInstance();

        Member member = new Member(10L, "변영준", Grade.VIP);

// 공정 할인 정책 테스트
        DiscountPolicy fixDiscountPolicy = new FixDiscountPolicyImpl();
        DiscountPolicy percentDiscountPolicy = new PercentDiscountPolicyImpl();
        OrderService orderService1 = new OrderServiceImpl(memberRepository, fixDiscountPolicy);

        Order order1 = orderService1.createOrder(1L, "맥북", 10000);
        System.out.println(order1);
        System.out.println(order1.calculateDiscount());


    }

}

 

심화 2 - Configuration 설정
package config;

import member.repository.MemberRepository;
import member.repository.MemoryMemberRepositoryImpl;
import member.service.MemberService;
import member.service.MemberServiceImpl;
import order.*;

public class AppConfig {

    public MemberRepository getMemberRepository() {
        return MemoryMemberRepositoryImpl.getInstance();
    }

    public MemberService getMemberService() {
        return new MemberServiceImpl(getMemberRepository());
    }

    public DiscountPolicy getDiscountPolicy() {
// 이 부분만 바꾸면 됨// return new FixDiscountPolicyImpl();return  new PercentDiscountPolicyImpl();
    }

    public OrderService getOrderService() {
        return new OrderServiceImpl(getMemberRepository(), getDiscountPolicy());
    }

}

 

Main Class
package config;

import member.Grade;
import member.Member;
import member.service.MemberService;
import order.Order;
import order.OrderService;

public class MainApp {

    public static void main(String[] args) {


        AppConfig appConfig = new AppConfig();

// 클라이언트 입장에서 코딩// 회원 가입 기능이 필요함.
        MemberService memberService = appConfig.getMemberService();
        Member member = new Member(200L, "도시락", Grade.VIP);
        memberService.signUp(member);// 회원 가입// 사용자 주문 요청
        OrderService orderService1 = appConfig.getOrderService();
        Order order1 = orderService1.createOrder(member.getId(), "아이폰16", 3_000);
        System.out.println(order1);
        System.out.println(order1.calculateDiscount());

    }

}