興味のある分離


これまでのコード


アプリケーションをショーに想像します.各インタフェースをキャラクタ(俳優キャラクタ)とする.
以前のコードは、ロミオ役(インタフェース)を演じたレオナルド・ディカプリオ(具象体、俳優)がジュリエット役(インタフェース)を演じたヒロイン(具象体、俳優)を直接招聘したようなものだった.
現在は、演出を組織し、担当俳優を招き、役にふさわしい俳優を指定する別の演出企画者が現れる時だ.
演出プランナーを創設し、俳優と演出プランナーの責任を明確に分離する.

AppConfigが表示されます


アプリケーションの完全な動作(config)を構成するために、実装オブジェクトの作成と接続を担当する個別の設定クラスを作成します.
 package hello.core;

import hello.core.discount.FixDiscountPolicy;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.member.MemoryMemberRepository;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;

public class AppConfig {
    public MemberService memberService(){
        return new MemberServiceImpl(new MemoryMemberRepository());
    }

    public OrderService orderService(){
        return new OrderServiceImpl(new MemoryMemberRepository(), new FixDiscountPolicy());
    }
}
AppConfigは、アプリケーションの実際の操作に必要な実装オブジェクトを生成します.
AppConfigは、作成したオブジェクトインスタンスの参照をコンストラクタを介して注入(接続)します.
package hello.core.member;

public class MemberServiceImpl implements MemberService{

    private final MemberRepository memberRepository;
  
    public MemberServiceImpl(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Override
    public void join(Member member) {
        memberRepository.save(member);
    }

    @Override
    public Member findMember(Long memberId) {
        return memberRepository.findById(memberId);
    }
}
今は抽象化に頼っているだけだ.生成者注入依存関係を利用して生成者注入と呼ぶ.
MemberServiceImplはこれから依存関係への悩みを外部に任せ,実行に専念すればよい.
package hello.core.order;

import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.discount.RateDiscountPolicy;
import hello.core.member.Member;
import hello.core.member.MemberRepository;
import hello.core.member.MemoryMemberRepository;

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) {

        /**
         * 설계가 잘되어 있는 것 orderService는 Discount에 대해서 전혀 모르고 있기 때문이다
         */
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);
        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

package hello.core;

import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.order.Order;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;

public class OrderApp  {
   public static void main(String[] args) {
       AppConfig appConfig = new AppConfig();
       MemberService memberService = appConfig.memberService();
       OrderService orderService =appConfig.orderService();

       Long memberId = 1L;
       Member member = new Member(memberId, "memberA", Grade.VIP);
       memberService.join(member);

       Order order = orderService.createOrder(memberId, "itemA", 10000);

       System.out.println("order = " + order.toString());

   }
}