Build, Execution, Deployment > Build Tools > Gradle
위와 같이 IntelliJ IDEA
로 변경한다. IntelliJ 에서 자바를 바로 돌려서 Gradle로 했을 때보다 빠르다.
🤨 요구 사항을 보면 회원 데이터와 할인 정책은 정책이 완전히 정해지지 않음
개발은 당장 시작해야한다.
⇒ 인터페이스를 만들고 구현체를 언제든지 갈아 끼울 수 있어야 한다 !
⇒ 앞에서 배운 객체 지향 설계 방법을 이용해서 비즈니스 요구 사항대로 설계해보자
❗ 지금은 순수하게 자바만을 이용해서 설계한다.
회원 저장소 인터페이스
public interface MemberRepository {
void save(Member member);
Member findById(Long memberId);
}
메모리 회원 저장소 구현체
public class MemoryMemberRepository implements MemberRepository{
private static Map<Long, Member> store = new HashMap<>();
@Override
public void save(Member member) { store.put() };
@Override
public Member findById(Long memberId) { store.get() };
}
회원 서비스 인터페이스
public interface MemberService {
void join(Member member);
Member findMember(Long memberId);
}
회원 서비스 구현체
public class MemberServiceImpl implements MemberService {
// 회원 가입/조회 하려면 MemberRepository가 필요하다.
private final MemberRepository memberRepository = new MemoryMemberRepository;
@Override
void join(Member member){ memberRepository.save(member); }
@Override
Member findMember(Long memberId){ return memberRepository.findById(memberId); }
}
✍️ ConcurrnetHashMap
실무에서는 동시성 이슈때문에HashMap
이 아닌ConcurrnetHashMap
을 사용한다
✍️ MemberServiceImpl
관례상 인터페이스의 구현체가 1개만 존재할 경우에는 뒤에Impl
을 붙여 클래스를 만든다.
public class MemberServiceImpl implements MemeberService {
// 인터페이스 **MemberRepostiory**
// 구현체 **MemoryMemberRepository**
**private final MemberRepostiory memberRepostiory = new MemoryMemberRepository();**
@Override
public void join(Member member) {
memberRepository.save(memeber);
}
}
public class MemberApp {
public static void main(String[] args) {
MemberService memberService = new MemberServcieImpl();
Member memeber = new Member(1L, "memberA", Grade.VIP);
memeberService.join(member); // 회원가입
Member findMember = memberService.findMember(1L);
System.out.println("new member = " + member.getName()); // memberA
System.out.println("find member = " + findMember.getName()); // memberA
}
}
이 방법은 매번 눈으로 결과를 보며 직접 확인해야한다.
import org.assertj.core.api.Assertions;
public class MemberServiceTest {
MemberService memberService = new MemberServiceImpl();
@Test
void join() {
// given
Member member = new Member(1L, "memberA", Grade.VIP);
// when
memberService.join(member);
Member findMember = memberService.findMember(1L);
// then
Assertions.assertThat(member).isEqulsTo(findMember);
}
}
✍️ OCP 원칙 ( Open Close Principle) : 개방폐쇄의 원칙
확장에 대해서는 Open, 변경에 대해서는 폐쇄(Close)
→ 기존의 코드를 변경하지 않으면서 기능을 추가할 수 있도록 설계해야한다.
✍️ DIP 원칙 (Dependency Inversion Principle) : 의존 역전 원칙
자주 변경되는 구체 클래스에 의존하지마라.
ex. 자동차(인터페이스) 겨울 타이어에 의존한다. → 계절이 바뀌면 다시 변경해야한다. → DIP 위배
자동차가 구체적인 타이어(겨울, 일반, 광폭)가 아닌 추상화된 타이어 인터페이스에만 의존하게 한다.
public class MemberServiceImpl implements MemeberService {
// 인터페이스(추상화)뿐만 아니라 구현체(구체화)에도 의존하고있다. -> DIP 위반
private final MemberRepostiory memberRepostiory = new MemoryMemberRepository();
...