#3 ์คํ๋ง ํต์ฌ ์๋ฆฌ - ๊ธฐ์กด์ ๋ถํธํ ์ค๊ณ ๋ฐฉ์
by JiwonDevํด๋น ๊ธ์ ๊น์ํ๋์ ์ธํ๋ฐ ๊ฐ์๋ฅผ ๊ณต๋ถํ๊ณ ์ ๋ฆฌํ ๋ด์ฉ์ ๋๋ค.
์คํ๋ง ์์ด ์์ํ ์๋ฐ์ฝ๋๋ก ๋น์ฆ๋์ค ์๋น์ค๋ฅผ ๋ง๋ค์ด๋ณด์.
# ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ
๋ค์๊ณผ ๊ฐ์ ๊ธฐํ์์ ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ์ด ์๋ค๊ณ ๊ฐ์ ํด๋ณด์. ์๊ตฌ์ฌํญ ์ค์๋ ์์ง ํ์ ๋์ง ์์๊ฑฐ๋, ๊ฐ๋ฐ ๋์ค ๋ณ๊ฒฝํ ์๋ ์๋ ๋ด์ฉ๋ค์ด ํฌํจ๋์ด ์๋ค.
# ํ์
# ํ์ ๋๋ฉ์ธ ์ค๊ณ
์ฐ์ , ๋น์ฆ๋์ค์ ํต์ฌ์ธ ํ์์ ๋๋ฉ์ธ์ ๋ํด ์ค๊ณ๋ฅผ ์์ํด๋ณด์.
๋๋ฉ์ธ์ด ๋ญ์ฃ
ํด๊ฒฐํ๊ณ ์ ํ๋ ๋ฌธ์ ๋ฐ ๊ด์ฌ์ฌ๋ฅผ ๋๋ฉ์ธ(Domain)์ด๋ผ๊ณ ํํํ๋ค. ์๋ฅผ ๋ค์ด ์์ ์๋น์ค๋ฅผ ๋ง๋ค๊ณ ์ ํ๋ค๋ฉด, ๋๋ฉ์ธ์ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌ์ฑํ ์ ์๋ค.
์ด๋ ๊ฒ ๋ง๋ ๋๋ฉ์ธ ๋ชจ๋ธ์ ๋ฐํ์ผ๋ก ๊ตฌ์ฒดํํ์ฌ ํด๋์ค ๋ค์ด์ด๊ทธ๋จ๊ณผ ๊ฐ์ฒด ๋ค์ด์ด๊ทธ๋จ์ ๋ง๋ ๋ค.
ํ์ฌ ์ฃผ์ด์ง ํ์ ๋๋ฉ์ธ์ ์๊ตฌ์ฌํญ์ ์๋์ ๊ฐ๋ค.
- ํ์์ ๊ฐ์
ํ๊ณ ์กฐํํ ์ ์๋ค
⇒ ํ์๊ฐ์ ๊ณผ ์กฐํ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ [ํ์ ์๋น์ค] ๋ฅผ ๋ง๋ ๋ค. - ํ์์ ์ผ๋ฐ๊ณผ VIP ๋ ๊ฐ์ง ๋ฑ๊ธ์ด ์๋ค.
⇒ ํ์ ๋๋ฉ์ธ์ ๋ฑ๊ธ ์ ๋ณด๋ฅผ ๊ฐ์ง๋ค. Enum ์ ์ด์ฉํ์ฌ ๋ฑ๊ธ์ ๋ํ๋ด๋ ํ์ ์ ๋ง๋ ๋ค. - ํ์ ๋ฐ์ดํฐ ์์ฒด DB๋ฅผ ๊ตฌ์ถํ ์ ์๊ณ , ์ธ๋ถ ์์คํ
๊ณผ ์ฐ๋ํ ์ ์๋ค.(๋ฏธํ์ )
⇒ ํ์ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๋ ์ญํ , [ํ์ ์ ์ฅ์] ์ธํฐํ์ด์ค๋ฅผ ๋ง๋ ๋ค.
์ด๋ ๊ฒ ๋ง๋ ๋๋ฉ์ธ์ ์ด์ฉํ์ฌ ๊ฐ์ฒด & ํด๋์ค ๋ค์ด์ด๊ทธ๋จ์ ๋ง๋ค์ด๋ณด์.
- [ํ์ ์๋น์ค]๋ MemberService ์ธํฐํ์ด์ค(์ญํ )์ ๋ง๋ค๊ณ MemberServiceImpl๋ก ๊ตฌํํ๋ค.
- [ํ์ ์ ์ฅ์]๋ MemberRepository ์ธํฐํ์ด์ค(์ญํ )์ ๋ง๋ค๊ณ ๊ฐ ์ ์ฅ์๋ณ ๊ตฌํ์ฒด๋ฅผ ๊ตฌํํ๋ค.
๋๋ฉ์ธ๊ณผ ํด๋์ค ๋ค์ด์ด๊ทธ๋จ์ด ์์ฑ๋์๋ค๋ฉด, ์ค์ ์๋ฒ์์ ๊ฐ์ฒด๊ฐ ์ฐธ์กฐ๊ฐ ์ด๋ป๊ฒ ๋๋์ง๋ฅผ ๊ทธ๋ฆฐ๋ค. ์ด๋ฅผ ๊ฐ์ฒด ๋ค์ด์ด๊ทธ๋จ์ด๋ผ ํ๋ฉฐ ์ค์ ์๋น์ค๊ฐ ์ด๋ป๊ฒ ๋์ ๋๋์ง ํ๋์ ๋ณผ ์ ์๋ค.
- ํด๋ผ์ด์ธํธ๋ ํ์์๋น์ค๋ฅผ ํธ์ถํ๊ณ , ํ์ ์๋น์ค๋ ํ์ ์ ์ฅ์๋ฅผ ์ฐธ์กฐํ์ฌ ๋น์ฆ๋์ค ๋ก์ง์ ์คํํฉ๋๋ค.
์ด๋ฅผ ๋ฐํ์ผ๋ก ์ง์ ์์ฑํ ์๋ฐ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
- ๋๋ฉ์ธ (Member, Grade)
public enum Grade {
BASIC,
VIP
}
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;
}
// ... getter setter ์๋ต ...
}
- ์๋น์ค (MemberService, MemberServiceImpl)
public interface MemberService {
void join(Member member);
Member findMember(Long memberId);
}
public class MemberServiceImpl implements MemberService {
public final MemberRepository memberRepository = new MemoryMemberRepository();
@Override
public void join(Member member) {
memberRepository.save(member);
}
@Override
public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
}
- ์ ์ฅ์ (MemberRepository, MemoryMemberRepository)
public interface MemberRepository {
void save(Member member);
Member findById(Long memberId);
}
public class MemoryMemberRepository implements MemberRepository {
public static Map<Long, Member> store = new HashMap<>();
@Override
public void save(Member member) {
store.put(member.getId(), member);
}
@Override
public Member findById(Long memberId) {
return store.get(memberId);
}
}
# ํ์ ๋๋ฉ์ธ ์คํ๊ณผ ํ ์คํธ
์์ฑํ ์ฝ๋๋ค์ด ์ ์๋ํ๋์ง ์๋น์ค ๊ณ์ธต๋ถํฐ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํด์ ํ์ธํด๋ณด์.
import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
// ์ฑ ์ง์
์
public class MemberApp {
public static void main(String[] args) {
MemberService memberService = new MemberServiceImpl();
Member member = new Member(1L, "memberA", Grade.VIP);
memberService.join(member);
Member findMember = memberService.findMember(1L);
System.out.println("new member = " + member.getName());
System.out.println("findMember = " + findMember.getName());
}
}
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
// JUnit์ ์ด์ฉํ ํ
์คํธ
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).isEqualTo(findMember);
}
}
# ํ์ ๋๋ฉ์ธ ํ๊ฐํ๊ธฐ
ํ์ ๋๋ฉ์ธ์ ์ค๊ณ์ ํ ์คํธ๋ฅผ ์ฑ๊ณตํ๋ค. ์ ๊ทธ๋ ๋ค๋ฉด ํด๋น ์ฝ๋๋ ๊ฐ์ฒด์งํฅ์์ ๋งํ๋ SOLID ์์น์ OCP, DIP๋ฅผ ๋ง์กฑํ๊ณ ์๋๊ฐ? ๋คํ์ฑ์ด ์ ์ค๊ณ๋ ์ฝ๋์ผ๊น?
- ํ์ ์ ์ฅ์๋ก MemberRepository๋ฅผ ์ฌ์ฉํ ๋ ๋์ค์ ์ ์ฅ์๋ฅผ ๋ณ๊ฒฝํ ๋ OCP ์์น์ด ์ง์ผ์ง ์ ์๋๊ฐ?
- DIP๊ฐ ์ ์ง์ผ์ง๊ณ ์๋๊ฐ?
์๋๋ค. ์์กด๊ด๊ณ๊ฐ ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด์ ๋ชจ๋ ์๋ค. ์ผ๋จ์ ๋์ด๊ฐ๋๋ก ํ๊ณ , ์ฃผ๋ฌธ๊ณผ ํ ์ธ์ ์ค๊ณํด๋ณด์.
# ์ฃผ๋ฌธ๊ณผ ํ ์ธ
# ์ฃผ๋ฌธ๊ณผ ํ ์ธ ๋๋ฉ์ธ ์ค๊ณ
- ํ์์ ์ํ์ ์ฃผ๋ฌธํ ์ ์๋ค.
- ํ ์ธ ์ ์ฑ ์ ๋ชจ๋ VIP๋ 1000์์ ํ ์ธํด์ฃผ๋ ๊ณ ์ ๊ธ์ก ํ ์ธ์ ์ ์ฉํด๋ฌ๋ผ.(๋ณ๊ฒฝ๊ฐ๋ฅ)
- ํ ์ธ ์ ์ฑ
์ ๋ณ๊ฒฝ ๊ฐ๋ฅ์ฑ์ด ๋๋ค. ํ์ฌ์ ๊ธฐ๋ณธ ํ ์ธ ์ ์ฑ
์ ์์ง ์ ํ์ง ๋ชปํ๋ค.
์คํ ์ง์ ๊น์ง ๊ณ ๋ฏผ์ ๋ฏธ๋ฃจ๊ณ ์ถ๋ค. ์ต์ ์ ๊ฒฝ์ฐ ํ ์ธ์ ์ ์ฉํ์ง ์์ ์ ์๋ค. (๋ฏธํ์ )
์ฃผ๋ฌธ๊ณผ ํ ์ธ์ ๋ํ ์ ์ฑ ๊ณผ ์๊ตฌ์ฌํญ์ ๋ถ์ํด๋ณด์. ํ์์ ์ฃผ๋ฌธ์ ํ ์ ์๋๋ฐ, ํ์์ ๋ฑ๊ธ์ ๋ฐ๋ผ ์ํ์ ํ ์ธ์ด ์ ์ฉ๋ ์ ์๋ค. ์ด๋ฅผ ์ ๋ฆฌํ๋ฉด ์๋ 4๊ฐ์ง๋ก ๋ง๋ค ์ ์๋ค.
- ์ฃผ๋ฌธ ์์ฑ: ํด๋ผ์ด์ธํธ๋ ์ฃผ๋ฌธ ์๋น์ค์ ์ฃผ๋ฌธ ์์ฑ์ ์์ฒญํ๋ค.
- ํ์ ์กฐํ: ํ ์ธ์ ์ํด์ ํ์ ๋ฑ๊ธ์ ์์์ผํ๊ธฐ์ ํ์์ ์กฐํํ๋ค.
- ํ ์ธ ์ ์ฉ: ํ์ ๋ฑ๊ธ์ ๋ฐ๋ฅธ ํ ์ธ์ฌ๋ถ์ ํ ์ธ ๊ธ์ก์ ์๊ธฐ ์ํด ํด๋น ์ฑ ์์ ํ ์ธ ์ ์ฑ ์ญํ ์ ์์ํ๋ค.
- ์ฃผ๋ฌธ ๊ฒฐ๊ณผ ๋ฐํ: ์ฃผ๋ฌธ ์๋น์ค๋ ํ ์ธ ๊ฒฐ๊ณผ๋ฅผ ํฌํจํ ์ฃผ๋ฌธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ค.
๋ง๋ค์ด๋ ผ ์ค๊ณ๋ฅผ ๋ฐํ์ผ๋ก ํด๋์ค์ ๊ตฌ์ฑ๋๋ฅผ ๊ทธ๋ ค๋ณด์. ๊ฐ์ฒด๋ฅผ ์ง์ ์ฐ๊ฒฐํ๋๊ฒ ์๋ ์ญํ (์ธํฐํ์ด์ค)์ ๊ตฌํ(๊ฐ์ฒด)๋ฅผ ๋ถ๋ฆฌํ๋ค. ์ด๋ ๊ฒ "์ญํ ๊ณผ ๊ตฌํ์ ๋ถ๋ฆฌ"ํด์ ์ค๊ณํ์ฌ์ผ [ํ์ ์ ์ฅ์]๋ [ํ ์ธ ์ ์ฑ ]์ ์ ์ฐํ๊ฒ ๋ณ๊ฒฝํ ์ ์๋ค.
๋๋ฉ์ธ๊ณผ ํด๋์ค๋ฅผ ๋ฐํ์ผ๋ก ๊ฐ์ฒด๊ฐ์ ์ฐธ์กฐ ๊ด๊ณ๋ฅผ ๊ทธ๋ฆฐ๋ค.
์ฃผ๋ฌธ๊ณผ ํ ์ธ์ ์ฑ ์ ๊ด๋ จํ์ฌ ๋๋ฉ์ธ๊ณผ ์ญํ (์ธํฐํ์ด์ค)์ ์ฐจ๋ก๋๋ก ์์ฑํด๋ณด์. ์ค์ ์ค๊ณ์์๋ '์ํ'๋ ๋๋ฉ์ธ์ผ๋ก ๋ง๋ค์ด ๊ฐ์ฒด ์ค๊ณ๋ฅผ ํด์ผํ์ง๋ง ์ด๋ฒ ์์ ์์๋ ๊ฐ๋จํ๊ฒ ์ํ์ ์ด๋ฆ๊ณผ ๊ฐ๊ฒฉ๋ง ๋ฐ์ดํฐ๋ก ๋ฐ๋๋ก ๋ง๋ค์๋ค.
์ฃผ๋ฌธ๋๋ฉ์ธ (Order)
package hello.core.discount;
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 calculatePrice() {
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 +
'}';
}
}
์ฃผ๋ฌธ ์๋น์ค ์ญํ , ์ธํฐํ์ด์ค(OrderService)
public interface OrderService {
Order createOrder(Long memberId, String itemName, int itemPrice);
}
ํ ์ธ ์ ์ฑ ์๋น์ค ์ญํ (DiscountPolicy)
public interface DiscountPolicy {
/**
* @return ํ ์ธ ๋์ ๊ธ์ก
*/
int discount(Member member, int price);
}
์ธํฐํ์ด์ค ์ค๊ณ๋ฅผ ์๋ฃํ๋ค๋ฉด, ๋ฐ๋ก ์๋์ ๊ตฌํ์ฒด๋ฅผ ๋ง๋ค์ด๋ ๋์ง๋ง, ์ ๊น ๋์ด๊ฐ์ ํ ์คํธ์ฝ๋๋ถํฐ ์์ฑํด๋ณด์. ์ด๋ ๊ฒ ํ ์คํธ ์ฝ๋๋ฅผ ๋จผ์ ์์ฑํ๋ฉด ์ด๋ค ์ด์ ์ด ์์๊น?
//DiscountPolicy ๊ตฌํ์ฒด
public class FixDiscountPolicy implements DiscountPolicy{
private int discountFIxAmount = 1000; // 1000์ ํ ์ธ
@Override
public int discount(Member member, int price) {
if (member.getGrade() == Grade.VIP) {
return discountFIxAmount;
}
return 0;
}
}
//OrderSevice ๊ตฌํ์ฒด
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository = new MemoryMemberRepository();
private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
@Override
public Order createOrder(Long memberId, String itemName, int itemPrice) {
Member member = memberRepository.findById(memberId);
int discount = discountPolicy.discount(member, itemPrice);
return new Order(memberId, itemName, itemPrice, discount);
}
}
# ์ฃผ๋ฌธ๊ณผ ํ ์ธ ๋๋ฉ์ธ ๊ตฌํ๊ณผ ํ ์คํธ
@DisplayName("OderService ํด๋์ค์")
class OrderServiceTest {
private Member basicMember;
private Member vipMember;
private OrderService orderService;
private MemberService memberService;
@BeforeEach
void setup() {
orderService = new OrderServiceImpl();
memberService = new MemberServiceImpl();
basicMember = new Member(1L, "BASIC", Grade.BASIC);
vipMember = new Member(2L, "VIP", Grade.VIP);
memberService.join(basicMember);
memberService.join(vipMember);
}
@Nested
@DisplayName("createOrder ๋ฉ์๋๋")
class Describe_createOrder {
@Nested
@DisplayName("์ผ๋ฐ ๋ฑ๊ธ์ ํ์์ด 10000์์ง๋ฆฌ ๋ฌผ๊ฑด์ ์ฃผ๋ฌธ์ ์์ฑํ ๊ฒฝ์ฐ ๊ฐ๊ฒฉ์")
class Context_with_create_order_from_basic_member {
@DisplayName("์ ํ์ ๋ฌผ๊ฑด ๊ฐ๊ฒฉ ๊ทธ๋๋ก ์์ฑ๋๋ค.")
@Test
void it_is_original_price() {
//when
Order order = orderService.createOrder(basicMember.getId(), "item", 10000);
//then
assertThat(order.calculatePrice()).isEqualTo(10000);
}
}
@Nested
@DisplayName("VIP๋ฑ๊ธ์ ํ์์ด 10000์์ง๋ฆฌ ๋ฌผ๊ฑด์ ์ฃผ๋ฌธ์ ์์ฑํ ๊ฒฝ์ฐ ๊ฐ๊ฒฉ์")
class Context_with_create_order_from_vip_member {
@DisplayName("์ ํ์ ๋ฌผ๊ฑด ๊ฐ๊ฒฉ ๊ทธ๋๋ก ์์ฑ๋๋ค.")
@Test
void it_is_discounted_price() {
//when
Order order = orderService.createOrder(vipMember.getId(), "item", 10000);
//then
assertThat(order.calculatePrice()).isEqualTo(9000);
}
}
}
}
# ์ด ์ฝ๋๋ OCP์ DIP๋ฅผ ์งํค๊ณ ์๋ ์ค๊ณ์ผ๊น?
์๋์ ๊ฐ์ด ์๋ก์ด ํ ์ธ ์ ์ฑ ์ ๋ง๋ ๋ค๊ณ ๊ฐ์ ํด๋ณด์.
์ ๋ ๊ธฐํ์: ์๋น์ค ์คํ ์ง์ ์ ํ ์ธ ์ ์ฑ ์ ์ง๊ธ์ฒ๋ผ ๊ณ ์ ๊ธ์ก ํ ์ธ์ด ์๋๋ผ ์ข ๋ ํฉ๋ฆฌ์ ์ธ ์ฃผ๋ฌธ ๊ธ์ก ๋น ํ ์ธํ๋ ์ ๋ฅ % ํ ์ธ์ผ๋ก ๋ณ๊ฒฝํ๊ณ ์ถ์ด์.
์๋ฅผ ๋ค์ด์ ๊ธฐ์กด ์ ์ฑ ์ VIP๊ฐ 10000์์ ์ฃผ๋ฌธํ๋ 20000์์ ์ฃผ๋ฌธํ๋ ํญ์ 1000์์ ํ ์ธํ๋๋ฐ, ์ด๋ฒ์ ์๋ก ๋์จ ์ ์ฑ ์ 10%๋ก ์ง์ ํด๋๋ฉด ๊ณ ๊ฐ์ด 10000์ ์ฃผ๋ฌธ์ 1000์์ ํ ์ธํด์ฃผ๊ณ , 20000์ ์ฃผ๋ฌธ์์ 2000์์ ํ ์ธํด์ฃผ๋ ๊ฑฐ์์!
์์ง ๊ฐ๋ฐ์: ์ ๊ฐ ์ฒ์๋ถํฐ ๊ณ ์ ๊ธ์ก ํ ์ธ์ ์๋๋ผ๊ณ ํ์์์. (์ข์ง์์ ์ปค๋ฎค๋์ผ์ด์ ์ ์1)
์ ๋ ๊ธฐํ์: ์ ์์ผ ์ํํธ์จ์ด ๊ฐ๋ฐ ์ ์ธ ๋ชฐ๋ผ์? “๊ณํ์ ๋ฐ๋ฅด๊ธฐ๋ณด๋ค ๋ณํ์ ๋์ํ๊ธฐ๋ฅผ”
์์ง ๊ฐ๋ฐ์: …
์ ์์ผ ์ํํธ์จ์ด ๊ฐ๋ฐ์ด๋?
์์์ ๊ตฌํ๊ณผ ์ญํ ์ ๊ตฌ๋ถํด๋จ๊ธฐ์ ๋จ์ํ ์๊ฐํ๋ฉด ์๋์ ๊ฐ์ด ์๋ก์ด ํ ์ธ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ , ํ ์คํธ ํด๋ณธ ๋ค ์ ์ฉ์์ผ์ฃผ๋ฉด ๋๋ค. ๊ธฐ์กด์ ๊ฐ๋ฐ๋ฐฉ์๋ณด๋ค๋ ํจ์ฌ ๊ฐ๋จํ๊ธด ํ๋ค. ํ์ค๋ง ๋ฐ๊พธ๋ฉด ๋๋๊น
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository = new
MemoryMemberRepository();
// ํ ์ธ์ ์ฑ
๊ตฌํ๋ถ ๋ณ๊ฒฝ!
// private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
@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);
}
}
@ ์จ๊ฒจ์ง ๋ฌธ์ ์
- ์ฐ๋ฆฌ๋ ์ญํ ๊ณผ ๊ตฌํ์ ์ถฉ์คํ๊ฒ ๋ถ๋ฆฌํ๋ค. OK
- ๋คํ์ฑ๋ ํ์ฉํ๊ณ , ์ธํฐํ์ด์ค์ ๊ตฌํ ๊ฐ์ฒด๋ฅผ ๋ถ๋ฆฌํ๋ค. OK
- OCP, DIP ๊ฐ์ ๊ฐ์ฒด์งํฅ ์ค๊ณ ์์น์ ์ถฉ์คํ ์ค์ํ๋ค..?
-> ๊ทธ๋ ๊ฒ ๋ณด์ด์ง๋ง ์ฌ์ค์ ์๋๋ค. - DIP: ์์กด์ฑ. ์ฃผ๋ฌธ ํด๋ผ๋( OrderServiceImpl )๋ DiscountPolicy ์ธํฐํ์ด์ค๋ง ์์กดํ๋ ์งํจ๊ฑฐ ์๋๊ฐ?
- ํด๋์ค๋ฅผ ๋ค์๋ณด์. ์ถ์(์ธํฐํ์ด์ค) ๋ฟ๋ง ์๋๋ผ ๊ตฌ์ฒด(๊ตฌํ) ํด๋์ค์๋ ์์กดํ๊ณ ์๋ค.
-> ์ถ์(์ธํฐํ์ด์ค) ์์กด: DiscountPolicy
-> ๊ตฌ์ฒด(๊ตฌํ) ํด๋์ค: FixDiscountPolicy , RateDiscountPolicy - OCP: ๋ณ๊ฒฝํ์ง ์๊ณ ํ์ฅํ ์ ์๊ฒ ์ค๊ณํด์ผ ํ๋ค.
์ง๊ธ ์ฝ๋๋ ๊ธฐ๋ฅ์ ํ์ฅํด์ ๋ณ๊ฒฝํ๋ฉด, ํด๋ผ์ด์ธํธ ์ฝ๋์ ์ํฅ์ ์ค๋ค! ๋ฐ๋ผ์ OCP๋ฅผ ์๋ฐํ๋ค.
๊ฒฐ๊ตญ ๊ตฌํ์ฒด ์ฝ๋๊ฐ ๋ฐ๋๋ฉด ๋ค๋ฅธ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํด์ผํจ์ ๋ณํจ์๋ค. ์กฐ๊ธ ๋ ํธํด์ก์ ๋ฟ, ์ญํ ๊ณผ ๊ตฌํ์ด ๋ถ๋ฆฌ๋์ง ์์ผ๋ฉด OCP์ DIP๊ฐ์ ๊ฐ์ฒด์งํฅ ์์น์ ์งํค์ง ๋ชปํ๋ค๋ ๋ง์ด๋ค.
@ ์๋ ๊ทธ๋ฌ๋ฉด ์ด๋ป๊ฒ OCP, DIP๋ฅผ ๊ตฌํํด์?
์ ๋ง ๊ฐ๋จํ๋ค. ์ธํฐํ์ด์ค(์ญํ )์ด ์๋ ๊ตฌํ๋ถ๋ถ์ ์ฝ๋์์ ์ ๊ฑฐํ๋ฉด ๋๋ค. ๊ทธ๋ผ DIP๋ฅผ ์ฝ๊ฒ ์งํฌ ์ ์๋ค.
//private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
private final DiscountPolicy discountPolicy;
??????????? ๊ทธ๋ผ ๊ตฌํ์ฒด๊ฐ ์๋๋ฐ ์ด๋ป๊ฒ ์ฝ๋๋ฅผ ์คํ์์ผ์? null์ ์คํ์์ผ์?
@ ํด๊ฒฐ๋ฐฉ์
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ๋๊ตฐ๊ฐ ํด๋ผ์ด์ธํธ์ธ 'OrderServiceImpl'์ 'DiscountPolicy' ์ ๊ตฌํ ๊ฐ์ฒด๋ฅผ ๋์ ์์ฑํ๊ณ , ์ฃผ์ ํด์ฃผ๋ฉด ๋๋ค. ์ด๊ฒ์ด ๋ฐ๋ก ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ์ด๋ค.
๊ธ์ด ๊ธธ์ด์ ธ, ๋ค์ ๊ธ์ ๊ณ์ ์ด์ด์ ์์ฑํ๊ฒ ์ต๋๋ค.
'๐ฑ Spring Framework > Spring Core' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
IoC, DI, ๊ทธ๋ฆฌ๊ณ ์ปจํ ์ด๋ (0) | 2021.08.02 |
---|---|
#4 ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ(SOC), ์์กด์ฑ ์ฃผ์ (DI) (0) | 2021.08.02 |
#2 ์คํ๋ง ํ๋ก์ ํธ ์์ฑ (0) | 2021.07.25 |
#1 ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ (0) | 2021.07.25 |
#0 ์คํ๋ง, ์๋ฐ์ ๋ด์ด ์ค๊ธฐ๊น์ง (0) | 2021.07.25 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev