📜 제목으로 보기

준비물(정책 조건과 액션)

  1. 정책 조건과 액션 종류
    1. 조건(-Condition)
      1. Sequence: 순서에 해당한다는 조건(혹은 선착순 몇명 안에 조건)
      2. Period: 특정 기간내에 해당한다는 조건(혹은 특정기간에 드는 조건)
      3. DayOfWeek: 특정 요일에 해당한다는 조건
      4. None: 조건없이 시행
    2. 액션(-Discount)
      1. Amount: 일정 금액을 Discount해준다.
      2. Percent: 일정비율을 Discount해준다.
      3. None: 할인 없음.

method1: trigger+action의 인터페이스 + 마커 인터페이스

설명

  1. 정책 condition 인터페이스: trigger와 action추상메서드를 다 가질 것임.

    1. 발동조건 검증 메서드 역할(추메)
    2. 액션 메서드 역할(추메)
  2. 정책 action 인터페이스: 마커인터페이스들을 내부에서 가짐.(enum과 비슷한 역할)

    • enum대신 인터페이스 속 마커 인터페이스들로 구성 됨.

    • 마커인 이유: 실제 정책내용을 같이 붙어다니는 조건 정책의 액션메서드에서 실제 정책내용을 구현할 예정

      1. 정책 trigger 인터페이스가 2개의 추상메서드(trigger, action)을 다 가진다.

      2. 정책action마커인터페이스를 구현한 정책action별 중간추상층(추상class)을 두어 1개의 추상메서드만 구현한다.

        • 이 때, 특정 action마커인터페이스 구현 && action메서드를 먼저 구현한 중간추상층으로 만들어야
      3. 정책을 적용할 객체 생성시, 특정 action 중간추상층 알도록(T자리에 대체)한 최종구상체를 선택하여 action이 적용된 객체를 생성할 수 있게 된다.

        image-20220629162111785

      4. 제네릭을 통해, 특정action추상층을 알게된 정책적용객체제네릭으로 알게된 만큼, 그 추상층를 생성자 인자로 사용하여, 생성자에서 구상체들을 받을 수 있게 된다.

      5. action별 중간추상층마다 condition별 최종구상층을 만들어서, condition메서드를 구현하여 구상화한다.

        image-20220629163810539

        image-20220629123058343

  • my)

    • 각각이 추상메서드로 가지는 인터페이스로 구현했다면?

      • DiscountPolicy인터페이스에 action메서드가 올라가며
      • DiscountCondition인터페이스의 trigger메서드도 같이 implements하여
      • 최종구상체는 2개의 메서드를 구상하게 된다.
      • 하지만, movie마다 특정 action정책을 줘야하는 카테고리화를 못한다(action별 추상층이 없다)
      • movie가 특정action에 대한 여러 condition들을 동시에 인자로 받을 수 없다(action별 추상층이 없다.)
    • action X condition의 조합의 상태에서,

      • 2가지 중 1가지로 카테고리화하려면, 추상층이 2개(action -> condition or condition -> action)여야하며
      • 카테고리 대상(action)인터페이스를 먼저 구현하는 중간추상층이 필요하다.
      • 조합의 나머지(condition)은 구상층에서 구현한다.
      • 상위 추상층은 2개의 메서드를 가지는 1개(DiscountCondition)로도 충분하지만
      • 1개 메서드를 구현한 중간추상층을 만들 때, 중간추상층별 나는 특정action 상층이다!를 나타내줄 마커인터페이스들이 필요하다.

      image-20220629172007035

실습

Action 중간추상층 1개 -> Condition+Action 최종구상체 1개 생성
  1. 정책을 적용할 객체를 정책주입 없이 먼저 구현한다.

    • 내부 정책이 적용될 대상메서드 등이 다 구현되어있어야한다.

      image-20220629174625128

  2. 적용할 정책을 설계해보기 위해, client에서 그림을 그려보기

    • 정책적용은 action(어떤 할인 적용할지) vs condition(어떤 조건에 적용할지) 2가지 카테고리가 있는 상태
      1. 각 카테고리마다 나올 2가지 전략메서드를 한개의 인터페이스에 몰아넣는다 생각한다.
      2. 먼저 1개는 중간추상층엑에서 구현 -> 나머지 1개는 최종구상체에 이름을 추가하여 구현한다고 생각한다
      3. 먼저 구현할 카테고리의 종류마다 -> 나머지 카테고리들을 가지게 된다고 생각한다.
        • action을 먼저 구현한다면
          • AmountDiscount, PercentDiscount (중간추상층 2개)
            • aAmountDiscount, bAmountDiscount, cAmountDiscount,dAmountDiscount (각 중간추상층 마다 4개)
            • aPercentDiscount, bPercentDiscount, cPercentDiscount,dPercentDiscount (각 중간추상층 마다 4개)
      4. 그렇다면, 2가지 카테고리 중 어느 카테고리를 먼저 선택할 것인지에 따라 중간추상층으로 먼저 구현하게 한다고 생각한다
      5. 정책적용 객체는 중간추상층을 upperbound로 제네릭을 적용하여 -> 해당 중간추상층을 구상체들만 알고서 인자/파라미터에 받을 수 있게하여 해당 카테고리의 1개만 적용할 수 있게 한다고 생각한다.
    • 아래의 예시는

      • action으로 먼저 카테고리화하고, 각 action마다 중간추상층을 만들 것이다.

      • 제네릭에 action중간추상층을 사용하면, 내부 T로 정의한 변수들은 중간추상층의 구상체들만 올 수있게 되므로, 해당action에 대한 condition들을 선택하여 집어넣을 수 있다.

        image-20220701133250205

  3. 먼저 적용할 카테고리인 action 중에 1개의 중간추상층condition 중 1개를 추가반영한 최종구상체 1개를 반영해 빨간줄로 만든다.

    • 최종구상체를 먼저 만들고 -> extends 중간추상층 -> impl 상위추상층 DiscountCondition을 만든다.
      • 상위추상층의 이름이 Condition인 이유는, **중간추상층에 action을 구현했다는 마커인터페이스를 DiscountPolicy 내부에서 만들것 이기 때문 **

image-20220701133309755

  1. 최종구상층 1개 -> 중간추상층 중 1개 -> action+condition 전략메서드 2개를 달 예정인, 상위 추상층 DiscountCondition -> action마커인터페이스를 순서대로 틀만 만든다.

    • 최종구상층을 1개를 먼저 만들되, 중간추상층을 상속하도록 만들고, 중간추상층도 상위추상층 DiscountCondition을 implements하도록 만든다.

      622e14b6-0dff-47ab-98e5-961d785e29d8

    • 사용 제네릭의 빨간줄을 해당class정의부에 T로 만들어주는 기능은 없다. -> 생성자에 파라미터 추가를 이용해 해당 제네릭에 최종구상체의 추상체인 중간추상층이 들어가도록 특정형 T -> upperbound 상위추상층으로 내부에 정의해서 빨간줄제네릭을 해결 하도록 해야한다.

      • 하지만, 제네릭 빨간줄 때문에 생성자 자동생성이 안된다. 잠시 지웠다가, 생성자에 T형(사용시 중간추상층 들어갈 예정) 파라미터로 들어가는 전략객체를 추가하고, T upperbound 상위추상층으로 정의 한뒤 사용제네릭을 다시 넣어주자.
        • T에는 최종구상체들의 추상체인 [중간추상층들이 사용]될 수 이도록 T type 파라미터 -> [T의 upperbound에 상위추상층]으로 지정해줘야한다.
          • 사용되는 제네릭 중간추상층은 T 정의시 직접적으로 사용X upperbound에 의해 결정되는 것이 제네릭의 특징
        • 최종구상체들의 파라미터를 T로 정의하여 생성자 인자 추가때, change signature에 추가 되는 인자에 대해 최종구상체 1개 deafult value로 들어가면 related problem들이 알아서 해결됨.

      f5a4f9a5-b0d1-4e12-9f8d-b2122aa7593c

    • 생성자에 주입받은 정책용 전략객체를 필드로 받아준다.

      image-20220701155331929

  2. 이제 정책적용에 필요한 2가지 전략메서드를 사용하면서 하나씩 정의하고 올려준다.

    • 할인정책을 적용할 메서드(calculateFee) 내부에서

      1. 정책 적용전 로직은 그대로 두고, early return을 활용하여 정책적용시 변화가 생길 field를 action메서드의 인자로 + 정책조건에 판단정보의 field를 trigger메서드의 인자로받아가며 아래와 같이 정의해준다.

        1. if 정책객체.isStatisFiedBy()를 사용하여 정책 조건trigger메서드를 사용하고
        2. if내부 early return에 기존 반환값 로직에서 정책을 적용하여 바뀔 부분나머지 로직을 나눈 뒤, 정책 적용 대상만 정책 적용action메서드의 인자로 사용한다. 이 때, 정책적용전 메서드 이름을 가져온다.

        image-20220701161018186

      b315ff3f-9b52-4bcd-9118-88f13bc0a6ea

      image-20220701155940305

  3. 빨간불로 최종구상체에서 작성한 2개의 전략메서드 create method하면 중간최상층을 지나 바로 -> 상위추상층(인터페이스)에 알아서 오페이터로 작성된다.

    • 최종구상체 : isSatisfiedBy의 2번째 카테고리(Condition)만 개별구현할 예정
    • 중간추상층 : calculateFee의 1번째 카테고리(Policy)만 개별구현할 예정
      • 이 때, 중간추상층마다 가질 action별 마커인터페이스를 달아줄 예정

    6763fa0c-661e-4668-a1f4-6be7025587c5

    image-20220701161744298

  4. 중간추상층은 2개의 오페이터 중 action 메서드만 먼저 구현하고, 최종구상층은 나머지 trigger 메서드를 구현한다. image-20220701162009758

    1. 중간추상층은 에서 action메서드 구현시, 정책 적용에 필요한 정보들은 추상클래스의 생성자주입으로 해결하고, 나중에 최종구상체들이 그 생성자주입부 + 필드를 super()로 물려받아 구상체 생성시 받아서 부모에게 넘겨준다

      2ed7522c-df2a-4a03-bff7-9f80c27bde55

      image-20220701162620673

    2. 주의! 중간추상층은 추상층으로서 개별구현이 구현되면 반드시 final로 자식이 못건들이게 막자 -> 추상층에 구현된 개별구현 method + 사용된 field

      image-20220701164435699

  5. 최종구상체는 실제 외부Client에서 생성되고, 값을 받아들이는 놈으로서 부모의 생성자주입에 필요한 값을 자식이 대신 받아 super()를 통해 부모선에서 처리되도록 던져준다.

    1701b44f-10f5-4457-8e26-6eeb63316d61

    image-20220701164832888

  6. 최종 구상체는 2개 전략메서드 중 1개인 정책조건trigger메서드를 구현하며, 필요한 것이 있으면 생성자로부터 받아서 정의한다.

    • Sequence -> Treatment정보에 찍혀있으며, 외부에서 입력해줄 선착순 sequence명에게만 적용되는 정책조건이라고 가정하자.

    9412b45b-4451-4dec-85b3-34eda2ea37a8

    image-20220701165529581

  7. 최종구상체의 주입을 받는 부분에서, 최종구상체의 생성자주입 인자 중간추상층(부모)용 1개 + 최종구상체용 1개 의 인자가 늘어나므로 deafult값을 미리 명시해놓고 주거나 안꼬이게 할려면, 미리 NONE정책으로 구현했어야할 듯 하다.

    image-20220701165922687

    • ctrl+F6으로 생성자에서 Sequence를 삭제후 바로 정책조건에 만족 안되는 값을 default로 주기

      • 중간추상층에 default값을 주면, 최종구상층에 적용되어버리니 하지말기
      • super()에 들어갈 부모를 위한 생성자인자최종구상층에서 지웠다가 default값과 함께 추가하기

      9049c127-7148-4c77-9dea-27a7eb708029

      d526c636-9875-4833-8604-5de5a6405ea4 image-20220701170329563

  8. 중간추상층의 abstract class에 Discountpolicy 카테고리인터페이스 > 개별 마커인터페이스로 1개 카테고리의 개별종류 표시하기

    • Amount외에 Percent, Count, None 등의 할인정책action들이 있다.
    • 메서드가 없는 마커인터페이스를 만들고, 하위 최종구상체들을 묶어줄 카구체 테고리를 표시한다.
      • 현재 Condition X policy의 조합인데, 인터페이스가 그만큼 명시되어있어야하며, Amount계열/Pecent계열의 최종구상체를 묶어서 한번에 처리할 수 있다?
        • 추상클래스론 안되는가??
    1. DiscountPolicy의 카테고리 인터페이스를 만든다.

      image-20220701174315226

    2. 인터페이스 내부에서 마커인터페이스들을 만든다.

      • 인터페이스 내부 인터페이스는 상위인터페이스{}extends하여 구현한다.

      image-20220701181420024

    3. 완성된 action중간추상층에 마커인터페이스를 추가 impl한다.

      • extends상속은 1개만 되지만,
      • 카테고리 인터페이스의 implements는 콤마로 여러 개 할 수 있다.

      image-20220701181633711

    4. 중간추상층의 제네릭사용을 위한 정책적용객체(Specialty)제네릭정의부 T의 upperbound를 중간추상층의 상위추상층을 줘야하는데, 1개더 추가되었을 땐, <T extends A & B>형태로 & 추가인터페이스를 주면 된다.

      image-20220701181902023

  9. 완성된 discountpolicy 관련 파일들을 discountpolicy패키지로 이동시키고, 개별 action중간추상층별로 패키지를 만들어서 관리한다.

    image-20220701182023449

    image-20220701182127338

최종구상체들추가 Condition+Action

image-20220702114805493

  1. 이제 AMOUNT계열의 Sequnce Trigger외 다른condition들을 반영한 최종구상체들을 늘려간다.

    1. AmountDiscount라는 중간추상층(추상클래스)가 인터페이스 2개와 1개의 전략메서드를 구현하고 있으니, 최종구상체는 추상클래스 1개 상속 및 super()에 전달위한 인자 생성자 주입만 해주면 된다.

      • Sequence 조건외에 Period, Weekend이 남았음

      9cb38c56-0459-4fea-9b38-00c06c0a9b78

    2. 추가된 2개의 AMOUNT계열 최종구상체의 trigger메서들 구현한다

DayOfWeekAmountDiscount

image-20220702113907731

image-20220702113952530

image-20220702113917236

PeriodAmountDiscount

image-20220702114034822

image-20220702114050396

Action 중간추상층 추가
  • action을 구현한 action 중간추상층은 아래과 같이 형성되어있다.

    1. package로 따로 분리해서, 하위에 condition을 단 최종구상체들이 오도록 한다.
    2. 2개의 오퍼레이터를 가진 상위추상층 DiscountPolicyaction에 대한 마커인터페이스 DiscounPolicy.XXXX 2개의 인터페이스를 구현한 추상클래스로 만든다.
    3. action메서드 구현에 필요한 것은 생성자 주입으로 받는다.
      • 추상메서드(오페레이터, 전략메서드)에서는 이미 시그니쳐가 정해져있음.

    e3f19794-3572-4d3a-93cb-038096223569

PercentDiscount

image-20220702124241422

NoneDiscount

image-20220702120315954

OverlappedDiscount -> 불가. action 1개당 1개의 condition만 배정되는 상태
  • 현재 movie에는 1개의 action - 1개의 condition이 반영된 최종구상체만 들어간다.
    • 만약, 1개의 action을 여러번 적용하려면, 정책적용 객체여러개의 정책객체를 받도록 해당계열 최종구상체들을 가변배열로 여러개 받게 한다.
정책적용 객체(Specialty)가 여러 정책객체(최종구상체)를 가지게 하기
  • action과 trigger를 동시에 가지는 정책객체이므로 여러 trigger를 돌면서 fee객체에 만족시마다 여러번 정책 적용시키도록, 생성자 주입 정책객체를 가변배열로 여러개 받도록 수정하기

    • 변경전

      image-20220702125635800

  1. 생성자 파라미터를 ... 가변배열로 바꾼다.

  2. 필드를 빈 Set으로 바꾼다.

  3. 생성자에서 배열 -> List -> addAll 으로 초기화해준다.

    010c1558-4d73-4569-b570-09e1a448855e

    image-20220702131044105

  4. 여러개의 정책객체를 for문으로 돌면서, 만족할때마다 적용시켜주며, 누적 적용에 대한 코드를 작성한다.

    1. .multi(count)는 1개당 가격에 정책이 다 적용된 뒤 곱해야한다.
    2. 여러개가 누적되서 적용이므로 누적적용용 재할당 누적변수를 for문 위에 만들어놓는다.
      • 내부에서 trigger를 만족할때마다 누적변수에 적용누적변수에 재할당한다.
    3. 마지막에 정책적용후 로직인 .multi(count)를 적용한다.

    image-20220702132713712

method2-1: 전략condition을 머금은 템플릿policy

설명

  • 참고 내 블로그object_part1_summary.html#discountpolicy-1)

  • as-is

    image-20220702164431579

    image-20220702163401201

    image-20220702171035277

  • to-be image-20220702164553323

    image-20220702214527693

    image-20220702235625410

  • 기존 discountpolicy 관련 로직을 다 삭제함

실습

  1. 정책적용 대상 객체(Specialty)에 action policy(템플릿)의 구상체부터 시작하되, step1의 2개 인터페이스 조합 -> action중간추상층을 생성 -> 특정 중간추상층을 사용하기 위한 제네릭 이 필요 없다.

    • 직전: 최종구상체 SequenceAmountDiscount -> action 중간추상층 AmountDiscount -> 그외 action추상층들을 제네릭으로 선택해야, 그 하위 condition조합된 최종구상층들을 받을 수 있었음.
    • 현재: condition전략을 선택해서 받은 action템플릿의 자식1개만 알면 된다.
      • 조합으로 인해 생긴 중간추상층이 없음 -> 제네릭 필요 없음.

    image-20220702175358898

    • 생성자 인자 추가시 change signature -> default value를 활용한다.
      • 기존에 생성되어 사용되고 있는 객체면, 자동으로 defaultValue 지정 change signature가 뜸.

    4cea01d0-f858-4213-a416-711282566b84

  2. 정책적용대상 객체 내부에서, 생성자로 받은 action템플릿 객체를 사용해서 -> 추상체 변수로 받으면서 추상클래스 생성 + public 템플릿메소드를 빨간줄로 완성해보자.

    • action템플릿메소드는 정책적용 필드 뿐만 아니라 내부에 머금을 condition을 위한 조건정보(treatment, count)도 같이 건네줘야한다.

    2d836cc3-f0f0-42ba-bd77-68518a7e3535

    image-20220702180820809

    • 템플릿 추상층만 만들었으니, 연결해준다.

      • 훅메서드를 만들어서 올리는 구조가 아니라서 직접 상속해준다.

      image-20220702183252725

  3. action템플릿을 작성할 때, 구상체로부터 올리는 것은 @Override + protected 훅메서드밖에 없으니 템플릿메소드부터 직접 작성해준다

    • 여기서 템플릿action에서는 여러개의 condition전략객체들을 알고 있다고 가정한다.
      • 여러 조건들을 다 적용시킬 예정
    • 템플릿 메소드 내에서 훅메서드 만드는 방법내수용 private메서드로 작성해서 proteced abstract로 빼야한다.
    1. conditions들을 반복문 돌리려면, DiscountCondition전략인터페이스 생성 -> 빈컬렉션으로 초기화 한다.
    2. condition의 trigger전략메서드를 사용하면서 정의한다.
    3. 개별action적용을 위해 내수용 메서드(객체없이 정의)를 통해정책을 적용할 필드(객체)에 훅메서드를 건다.
    4. 누적 적용을 위해서, 초기값(fee 파라미터)을 누적용 변수에 넣고, 누적용 변수에 적용해서 반복문 안에서 재할당한다.
    5. 적용된 객체를 반환한다.

    0a34e2a9-9984-4bf7-aa29-427e672285d3

    image-20220702182527647

  4. 템플릿policy를 직접 작성하여 내부 훅이 정의 (by 내수용 메서드)되었으면, 구상policy에서 훅을 구현하여 완성한다.

    83dc9bb7-6a04-4b65-ae0e-001cb7446ff7

    image-20220702213051959

  5. action템플릿(추상클래스)도 condition전략객체를 생성자 주입하는데 conditions가 여러개면서 유연하게 받으려면 빈컬렉션 초기화+ void setter(add)를 이용한다

    1. 여러 전략객체들을 받으며 -> 빈컬렉션 필드

      • 빈컬렉션으로 초기화한 순간 생성자에 자동주입은 안된다.
      • 생성자에서도 받아서 add하도록 시킬 수 있는데, 이럴 경우 생성시 반드시 입력해야해서 유연성이 사라져버린다는 단점이 생긴다.
    2. policy 생성후에도 condition들을 유연하게 추가 -> ( setter->add) 74425e91-8575-46f8-931b-55b954737ac3

      image-20220702183855502

    3. 외부에서는 지역변수로 미리 생성해놓고고 condition전략객체들을 add해서받는다. 75725ec8-1b16-4ba9-b0be-43721086fb05

      image-20220702184212613

  6. 구상 템플릿policy -> 추상 템플릿policy -> 구상템플릿policy 완성 -> 추상 전략condition -> 구상 전략condition순서로 개발 중이다.

    • 구상condition을 추상condition 변수자리에 넣어 사용하면서 만든다.

      • 구상 전략객체를 개별정의시, 역시 필요한 정보는 생성자 주입 받는다.

      8ad42169-147f-4f18-8cd1-fb80dde1acfa

      image-20220702213143740

  7. 전략condition 객체 1개와 전략condition을 먹금은 템플릿policy 구상체 1개가 만들어진 상태다.

    image-20220702214640301

    • 전략Condition과, 템플릿Policy가 따로 관리되므로 package를 분리해준다.

      image-20220702214813223

  8. 만들어진 구상체들을 테스트해준다.

    • 가장 하위계층에 있는 condition을 테스트하고 -> condition을 먹금은 템플릿policy을 테스트하는 순서대로 진행한다.

    • 템플릿의 구상체는 상속된 자식으로서 개별구현하는 훅메서드 이외에 보이지 않는 템플릿메소드 및 추상클래스에 정의한 필드 + 메서드들을 활용해야한다.

      image-20220702222121951

  9. 남은 전략Condition객체 생성

    • PeriodConditionimage-20220702231048260

    • DayOfWeekCondition

      image-20220702234127414

  10. 남은 템플릿policy 구상체들 생성. 템플릿의 구상체들은 훅메서드만 개별구현한다.

    • PercentPolicy

      image-20220702234640823

    • NonePolicy

      image-20220702235055319

method2-2: 템플릿policy를 일반class + 전략policy로 변환(2개의 전략객체를 사용하는 일반policy)

설명

image-20220703010442315

  • 현재 전략condition을 머금은 템플릿policy(확장시 조합폭발)를 확장가능성을 고려한 차악 일반policy클래스 + 전략action(의존성폭발)로 변경한다

    image-20220703010930908

    image-20220703121338772

  • step5

실습

  1. 템플릿메소드패턴의 추상클래스 DiscountPolicy를 -> 일반클래스로 바꾼다.

    1. abstract제거 & 훅메서드 정의 제거
    2. 템플릿메소드내 훅메서드(내수용메서드)앞에 전략객체(전략메서드+ -er) 소문자로 달아서 훅메서드 -> 전략객체.전략메서드()로 변경하여 개별구현시키기
    3. 전략객체를 필드로 생성후 생성자 주입
      • 현재 전략condition을 머금고 있기 때문에, 전략객체 2개를 사용하는 일반클래스가 된다.
      • 전략condition은 생성자 주입이 아니라, 빈컬렉션 -> 여러개+유연하게 setter(add)로 처리하는 중이다.
    4. 전략 인터페이스 및 오페레이터 완성
      • 전략이 들어가는 순간 strategy패키지로 파서 넣어주자.

    image-20220703125424909

    image-20220703122843764

  2. 템플릿메소드패턴의 구상체들을 전략객체로 변경한다. 구조가 유사하므로 조금만 바꿔준다.

    1. 클래스명을 구상내용+전략인터페이스명으로 변경

    2. 상속을 impl로 변경

      1. 상속관련 super() 등 삭제
    3. protected 훅메서드를 public 전략메서드로 접근제한자 변경

    4. 훅메서드명을 전략메서드로 변경

      • 메서드명 변경이나 삭제시 f2/alt+del 이용해서 변경/삭제할 것

      929d79a1-c499-4b7d-ab02-4bf2fc422a54

    image-20220703123552827

    • 나머지 템플릿 구상체들도 전략객체로 바꿔준다.

      image-20220703124134384

      image-20220703124208358

  3. Main이나 Test에서는 전략객체를 생성하고, 일반클래스 DiscountPolicy에 생성자 주입하도록 변경해서 사용한다.

    image-20220703125228058

method2-3: policy전략객체마다 위임&캐싱된 policy전략Factory 생성

설명

  • 생성 <-> 사용을 분리한다.
    • 생성해주는 Factory를 만든다.
      • Factory별 캐싱을 적용해서, 전략객체별-Factory객체 -> 전략객체별 한번만 만든다.
  • 생성(전략객체 생성)해주는 Factory가 사용(전략객체로 전략메서드 호출)의 책임까지 위임받는다.
    • 전략인터페이스 구현 -> 전략메서드 정의시 내부에서 생성->사용까지

image-20220703213949395

image-20220703213448253

image-20220703225131663

실습

  1. 전략인터페이스를 구현한 위임된 Factory를 생성하고, 정책적용객체(전략객체 주입)의 변수명을 전략객체 -> factory로 변경한다.

    • 위임된 팩토리는 전략객체별로 생성하며, 전략객체를 미리 생성 -> 강제 주입하는 대신전략객체 대신 factory로 주입하고 factory가 내부에서 전략객체를 필요시마다 캐싱하여 1회만 생성하며, 사용될때 생성을 한다.
      1. 전략인터페이스 구현한 Factory 생성
        • 기존 전략객체명 복사해놓은 상태 + Factory만 붙이기
      2. 정책적용 객체는 기존에는 미리 생성된 전략객체를 강제 주입 -> 전략객체 대신 factory를 주입할 예정

    70179341-05f7-4ce2-9be8-b7c60cb64ee0

    image-20220703212941879

    image-20220703213005159

  2. Factory가 구현해야할 전략메서드 내부에서, 내수용 & synchronized 캐싱 전략객체 생성메서드를 정의한 뒤, 전략메서드를 사용한다.

    1. 전략메서드 내부에서, 전략객체 생성 메서드create() or get전략객체 (내수용 + synchronized)를 작성하되, 내부에서 캐싱 적용
      • 빈 cache필드를 이용하여 없으면 재할당해서 채운다. 있으면 그대로 반환한다.

    2af594aa-420a-49a0-93fc-367202f7792c

    image-20220703223428293

  3. 정책적용 객체(DiscountPolicy)에 전략객체가 아닌 전략Factory를 주입시키도록 기존코드를 변경한다.

    90a18b29-ea0c-49be-a925-709840ec0bce

    image-20220703223504638