Object) TemplateMethod to Strategy2(Plan1)
훅메서드 -> 전략메서드 -> context공유로 책임커진, 연결되는 합성객체
📜 제목으로 보기
템플렛 메소드 패턴 -> 전략패턴
요약
- 전략적용대상의 class가 추상클래스로 개별로직을 가지는 상태
- 전략적용대상 추상class를 일반클래스로 변경 및 훅메서드 정의부 삭제
- 내수용 private훅메서드 호출부를, 주입된 전략객체.전략메서드()호출로 변경
- 전략 인터페이스 만들면서, 전략객체 주입 (생성자 or 확장(좋은 상속 가능성)있으면 setter로 받기)
- 전략메서드 올리기
- 훅메서드구현 개별자식들을 [구상내용+전략인페명]으로 변경하고, 전략인터페이스 구현
- @Override 개별구현 proected훅메서드 -> public전략메서드로 시그니쳐 변경
- 부모의 템플릿메소드 공통로직 with 내부 context변수들 -> 전체를 전략메서드에 인자로 context위임
- 내부context변수들(보라색)을 지역변수로 추출 이후 -> 제외하고 메서드 추출 -> 인라인으로 메서드인자로 context 넘겨주기
- delegate로 추출한 전체로직을 전략메서드에 default메서드로 위임
- 위임된 default메서드 로직에서, default를 지우고 로직을 개별 전략객체들에게 구현->전달후, 기존 전략메서드(context인자X)는 삭제
좋은 상속(템플릿메소드패턴) -> 합성객체(전략패턴)
템플릿메서드
는 기계적으로 전략패턴의 전략객체로 만들 수 있으며, 그 방법이 상속모델
-> 합성모델로 바꾸는 것과 마찬가지다
- 판단은 조합폭팔이 일어날 것 같을 때 기계적으로 바꾸면 된다.
- 연습은 상속이 보이면 조합으로 바꾸기(합성)를 해보면 된다.
-
템플릿추상클래스를 일반클래스로 내리고, 훅메서드 정의부 삭제하기
- 훅메서드가 내려가지 않고, 전략객체로 정의된 내용이 외부에서 주입된다.
-
훅메서드() 호출부를 전략객체.전략메서드()호출로 변경하기
- 추상클래스의 훅메서드 구상 자식클래스들을
- 전략객체가 대신한다.
- 추상클래스의 훅메서드 구상 자식클래스들을
-
전략객체를 생성자 주입하기전략객체를 생성자주입이 아닌void setter받기기능
으로 받기- 템플릿 추상클래스는
전략객체 주입 일반클래스
로 바뀌어도여전히 추상층으로서 확장(상속) 가능성이 있다면, 생성자 주입하면 안된다.
- 템플릿 추상클래스는
-
전략메서드 만들어서 올리기
-
훅메서드 구현체자식들을 전략객체로 변경
- 클래스명을
구상내용 + 전략인페명
으로 바꾸기 -
extedns
템플릿추상체
-> implements전략인터페이스
로 바꾸기 - protected훅메서드들 public전략메서드명으로 바꾸기
- 클래스명을
-
전략객체를 받기기능으로 받아,
상속(확장)가능성이 있다면 class에 final을 달지말고 3가지 원칙 지키는지 확인
하기- private변수
- final or protected abstract 메서드로 구성
- 생성자 주입 말고 받기기능으로 받을 것
최소 책임 전략 -> context를 공유하는 연결되는 합성객체
-
훅메서드의 최소 책임 합성 -> 연결되는 합성객체는 context를 공유받아 메서드단위(SRP)의 책임을 위임받을 수 있음.
-
현재 전략객체는
1개의 call
만 유틸메서드처럼 입력받아 값을 반환해주며 실질적으로 연산 전체의 상태(누적변수result, 초기값 Money.Zero)인 context를 위임받진 못하고 있다.-
하지만, 연결되는 합성객체가 되려면
해당 메서드내 context를 공유받아서 처리
해줘야제대로 책임위임
받는 것이다.- 훅메서드는 상속 특성상 최소의 구현만 맡고 있었고, 그것을 합성으로 변경하려다 보니, 합성객체는 context공유받아 관련 SRP를 전체로 책임질 수 있는데 못하고 있는 상태다.
-
하지만, 연결되는 합성객체가 되려면
-
기존 코드(Plan - 전략객체 적용(주입) class)
-
기존 전략객체의 작은 책임을 포함하여 전략적용 메서드 전체를 전략메서드로 빼기 위해
인자가 잡힌 내수용 메서드
로 추출한다.-
현재 적용객체 context의 시작 값들을 지역변수로 메서드 추출 위로 뺀다.
-
전략 인터페이스로 move시키기 위해 내수용으로 추출 후, 위에 빼놓은 지역변수를 인라인 으로 인자 자리에 넣어준다
- 미리 사용되는 변수들의 선언을 지역변수로 위에 빼놨기 때문에, 내수용메서드로 추출하여도 인자로 잡힌다.
-
-
인자잡힌 내수용 메서드를 move를 통해 전략 인터페이스로 이동시킨다.
- 구현부가 존재하니, default 메서드로 이동된다.
- 내부context로서 사용된 변수들이 인자가 이미 잡혀있으므로 잘못생긴
this 파라미터는 제거
한다
-
새로운 전략메서드에 기존 전략메서드가 내수용으로 사용되고 있다. ->
인라인 리팩토링으로 제거
될 예정이다- 새로운 전략메서드로서 default를 지우고, 구상체들이 구현하게 한다.
- default내용을 구현부를 복사해서 전략객체들이 구현부에 넣어준다.
- 기존 전략메서드는 inline refactoring을 이용해서 지운다.
- 기존 전략메서드를 인터페이스에서 지운다.
- 모든 전략객체에 구현부 복붙이 끝났으면, 전략메서드의 구현부도 삭제한다.