분류 전체보기 1341

Ch04. 프록시 패턴과 데코레이터 패턴 - 구체 클래스 기반 프록시(적용)

ContrlloerProxy public class OrderControllerConcreteProxy extends OrderControllerV2 { private final OrderControllerV2 target; private final LogTrace logTrace; public OrderControllerConcreteProxy(OrderControllerV2 target, LogTrace logTrace) { super(null); this.target = target; this.logTrace = logTrace; } @Override public String request(String itemId) { TraceStatus status = null; try { status = lo..

Ch04. 프록시 패턴과 데코레이터 패턴 - 구체 클래스 기반 프록시(테스트)

구체 클래스 기반 프록시 - 테스트(프록시 X) 구체 클레스(핵심 로직) @Slf4j public class ConcreteLogic { public String operation(){ log.info("ConcreteLogic 실행"); return "data"; } } 클라이언트 클래스 public class ConcreteClient { private ConcreteLogic concreteLogic; public ConcreteClient(ConcreteLogic concreteLogic) { this.concreteLogic = concreteLogic; } public void execute(){ concreteLogic.operation(); } } Test @Test public void ..

Ch04. 프록시 패턴과 데코레이터 패턴 - 인터페이스 기반 프록시(적용)

이전 의존관계 빈을 등록하는 설정 파일을 활용(클라이언트 코드 수정X) ContrlloerProxy @RequiredArgsConstructor public class OrderControllerInterfaceProxy implements OrderControllerV1 { private final OrderControllerV1 target; private final LogTrace logTrace; @Override public String request(String itemId) { TraceStatus status = null; try { status = logTrace.begin("OrderController.request()"); //target 호출 String result = target..

Ch04. 프록시 패턴과 데코레이터 패턴 - 프록시 패턴과 데코레이터 패턴 정리

생각해보면 Decorator 기능에 일부 중복이 있다 꾸며주는 역할을 하는 Decorator 들은 스스로 존재할 수 없다. 항상 꾸며줄 대상이 있어야 한다 따라서 내부에 호출 대상인 component를 가지고 있어야 한다. 그리고 component를 항상 호출해야 한다. 이 부분이 중복이다. 이런 중복을 제거하기 위해 component 를 속성으로 가지고 있는 Decorator라는 추상 클래스를 만드는 방법도 고민할 수 있다. 이렇게 하면 추가로 클래스 다이어그램에서 어떤 것이 실제 컴포넌트 인지, 데코레이터인지 명확하게 구분할 수 있다. 여기까지 고민한 것이 바로 GOF에서 설명하는 데코레이터 패턴의 기본 예제이다 프록시 패턴 vs 데코레이터 패턴 의도(intent) 의도에 따라 패턴을 구분한다. 프록..

Ch04. 프록시 패턴과 데코레이터 패턴 - 데코레이터 패턴

데코레이터 패턴 적용 전 - 예제 코드 작성 서버 - 인터페이스 public interface Component { String operation(); } 서버 - 실제 구현 클래스 @Slf4j public class RealComponent implements Component{ @Override public String operation() { log.info("RealComponent 실행"); return "data"; } } 클라이언트 @Slf4j public class DecoratorPatternClient { private Component component; public DecoratorPatternClient(Component component) { this.component = com..

Ch04. 프록시 패턴과 데코레이터 패턴 - 프록시 패턴

프록시 패턴 적용 전 - 예제 코드 작성 서버 - 인터페이스 public interface Subject { String operation(); } 서버 - 실제 구현 코드 @Slf4j public class RealSubject implements Subject{ @Override public String operation() { log.info("실제 객체 호출"); sleep(1000); return "data"; } private void sleep(int millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { e.printStackTrace(); } } } 클라이언트 public class ProxyPatternClien..

Ch04. 프록시 패턴과 데코레이터 패턴 - 프록시, 프록시 패턴, 데코레이터 패턴(소개)

이전의 요구사항을 만족하기 위해 기존 코드를 많이 수정해야 한다. 코드 수정을 최소화하기 위해 템플릿 메서드 패턴과 콜백 패턴도 사용했지만, 결과적으로 로그를 남기고 싶은 클래스가 수백 개라면 수백 개의 클래스를 모두 고쳐야 한다. 로그를 남길 때 기존 원본 코드를 변경해야 한다는 사실 그 자체가 개발자에게는 가장 큰 문제로 남는다 요구사항 추가 원본 코드를 전혀 수정하지 않고, 로그 추적기를 적용해라. 특정 메서드는 로그를 출력하지 않는 기능 보안상 일부는 로그를 출력하면 안된다. 다음과 같은 다양한 케이스에 적용할 수 있어야 한다. v1 - 인터페이스가 있는 구현 클래스에 적용 v2 - 인터페이스가 없는 구체 클래스에 적용 v3 - 컴포넌트 스캔 대상에 기능 적용 프록시 클라이언트와 서버 클라이언트(..

Ch04. 프록시 패턴과 데코레이터 패턴 - 예제 프로젝트 만들기

V1 - 인터페이스와 구현 클래스 -스프링 빈으로 수동 등록 Controller @RequestMapping //스프링은 @Controller 또는 @RequestMapping 이 있어야 스프링 컨트롤러로 인식 @ResponseBody public interface OrderControllerV1 { @GetMapping("/v1/request") public String request(@RequestParam("itemId") String itemId); @GetMapping("/v1/no-log") public String noLog(); } public class OrderControllerV1Impl implements OrderControllerV1{ private final OrderServi..

Ch03. 템플릿 메서드 패턴과 콜백 패턴 - 템플릿 콜백 패턴

ContextV2는 변하지 않는 템플릿 역할을 한다. 그리고 변하는 부분은 파라미터로 넘어온 Strategy의 코드를 실행해서 처리한다. 이렇게 다른 코드의 인수로서 넘겨주는 실행 가능한 코드를 콜백(callback)이라 한다. 콜백 프로그래밍에서 콜백(callback) 또는 콜 애프터 함수(call-after function)는 다른 코드의 인수로서 넘겨주는 실행 가능한 코드를 말한다. 콜백을 넘겨받는 코드는 이 콜백을 필요에 따라 즉시 실행할 수도 있고, 아니면 나중에 실행할 수도 있다. callback 은 코드가 호출( call )은 되는데 코드를 넘겨준 곳의 뒤( back )에서 실행된다는 뜻이다. ContextV2 예제에서 콜백은 Strategy 이다. 여기에서는 클라이언트에서 직접 Strate..

Ch03. 템플릿 메서드 패턴과 콜백 패턴 - 전략 패턴

Test @Slf4j public class ContextV1Test { @Test public void strategyV0(){ logic1(); logic2(); } private void logic1(){ long startTime = System.currentTimeMillis(); //비지니스 로직 실행 log.info("비지니스 로직1 실행"); //비지니스 로직 종료 long endTime = System.currentTimeMillis(); long resultTime = endTime - startTime; log.info("resultTime = {}", resultTime); } private void logic2(){ long startTime = System.currentTimeM..