요약
- 의존성 주입을 통해 객체 간의 결합도를 낮춥니다.
- 싱글톤 패턴을 사용하여 인스턴스를 공유합니다.
- 관심사 분리를 통해 설정과 비즈니스 로직을 분리하여 코드의 유지보수성을 높입니다.
- 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());
}
}
'Java > JAVA 3 - 유용한 클래스' 카테고리의 다른 글
Optional<T> - 부록 4 (0) | 2024.10.04 |
---|---|
Stream API - 부록 3 (2) | 2024.10.04 |
람다식(Lambda expression) - 부록 2 (2) | 2024.10.04 |
래퍼 클래스 - 부록 1 (0) | 2024.10.04 |
JSON 파싱 연습 2단계 - 32 (1) | 2024.06.07 |