프록시 패턴과 데코레이터 패턴 모두 프록시를 사용하는 방법이지만 GOF 디자인 패턴에서는 이 둘을 의도에 따라서 프록시 패턴과 데코레이터 패턴으로 구분한다.
- 프록시 패턴 : 접근 제어가 목적일 때
- 데코레이터 패턴 : 새로운 기능 추가가 목적일 때
프록시의 주요 기능
프록시를 통해서 할 수 있는 일은 크게 2가지로 구분할 수 있다.
- 접근 제어
- 권한에 따른 접근 차단
- 캐싱
- 지연로딩
- 부가 기능 추가
- 원래 서버가 제공하는 기능에 더해서 부가 기능을 수행한다.
- ex : 요청 값이나, 응답 값을 중간에서 변경하거나
- ex : 실행 시간을 측정해서 추가 로그를 남기거나
프록시 패턴 코드
정리 : 프록시 패턴의 핵심은 RealSubject 코드와 클라이언트 코드를 전혀 변경하지 않고, 프록시를 도입해서 접근 제어를 했다는 점이다. 그리고 클라이언트 코드의 변경 없이 자유롭게 프록시를 넣고 뺄 수 있다. 실제 클라이언트 입장에서는 프록시 객체가 주입되었는지, 실제 객체가 주입되었는지 알지 못한다.
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(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Slf4j
public class CacheProxy implements Subject{
private Subject target;
private String cacheValue;
public CacheProxy(Subject target) {
this.target = target;
}
@Override
public String operation() {
log.info("프록시 호출");
if(cacheValue==null){
cacheValue = target.operation();
}
return cacheValue;
}
}
public class ProxyPatternClient {
private Subject subject;
public ProxyPatternClient(Subject subject) {
this.subject = subject;
}
public void execute(){
subject.operation();
}
}
public class ProxyPatternTest {
@Test
void noProxyTest(){
RealSubject realSubject = new RealSubject();
ProxyPatternClient client = new ProxyPatternClient(realSubject);
client.execute();
client.execute();
client.execute();
}
@Test
void cacheProxyTest(){
RealSubject realSubject = new RealSubject();
CacheProxy cacheProxy = new CacheProxy(realSubject);
ProxyPatternClient client = new ProxyPatternClient(cacheProxy);
client.execute();
client.execute();
client.execute();
}
}
------------------
아래는 데코레이터 패턴 예제
public interface Component {
String operation();
}
@Slf4j
public class RealComponent implements Component{
@Override
public String operation() {
log.info("RealComponent 실행");
return "data";
}
}
@Slf4j
public class MessageDecorator implements Component{
private Component component;
public MessageDecorator(Component component) {
this.component = component;
}
@Override
public String operation() {
log.info("MessageDecorator 실행");
String result = component.operation();
String decoResult = "*****" + result + "*****";
log.info("MessageDecorator 꾸미기 적용 전 ={}, 적용 후={}", result, decoResult);
return decoResult;
}
}
@Slf4j
public class DecoratorPatternClient {
private Component component;
public DecoratorPatternClient(Component component) {
this.component = component;
}
public void execute(){
String result = component.operation();
log.info("result={}", result);
}
}
@Slf4j
public class DecoratorPatternTest {
@Test
void noDecorator(){
Component realComponent = new RealComponent();
DecoratorPatternClient client = new DecoratorPatternClient(realComponent);
client.execute();
}
@Test
void decorator1(){
Component realComponent1 = new RealComponent();
Component messageDecorator = new MessageDecorator(realComponent1);
DecoratorPatternClient client = new DecoratorPatternClient(messageDecorator);
client.execute();
}
@Test
void decorator2(){
Component realComponent1 = new RealComponent();
Component messageDecorator = new MessageDecorator(realComponent1);
Component timeDecorator = new TimeDecorator(messageDecorator);
DecoratorPatternClient client = new DecoratorPatternClient(timeDecorator);
client.execute();
}
}
'java > 디자인패턴' 카테고리의 다른 글
팩토리 메서드 패턴 (0) | 2023.02.14 |
---|---|
어뎁터 패턴 (adapter pattern) (0) | 2023.02.03 |
전략 패턴, 템플릿 콜백 패턴 (0) | 2022.10.08 |
전략 패턴 (0) | 2022.10.03 |
템플릿 메서드 패턴 (0) | 2022.10.02 |
댓글