1. Proxy Pattern
- Proxy는 대리인 이라는 뜻으로써, 뭔가를 대신해서 처리하는 것
- Proxy Class를 통해서 대신 전달하는 형태로 설계되며, 실제 CLient는 Proxy로 부터 결과를 받는다
- Cache의 기능으로도 활용이 가능하다
- SOLID 중에서 개방폐쇄 원칙(OCP)과 의존 역전 원칙(DIP)를 따른다
2. 프로젝트 테스트
- proxy 패키지 생성
- Interface : IBrowser
- Class : Html, Browser
01. Cache 기능 추가 전
package com.company.design.proxy;
public interface IBrowser {
Html show();
}
package com.company.design.proxy;
public class Html {
private String url;
public Html(String url) {
this.url = url;
}
}
package com.company.design.proxy;
public class Browser implements IBrowser{
private String url;
public Browser(String url) {
this.url = url;
}
@Override
public Html show() {
System.out.println("browser loading html from : "+url);
return new Html(url);
}
}
package com.company.design;
import com.company.design.proxy.Browser;
public class Main {
public static void main(String[] args) {
Browser browser = new Browser("www.naver.com");
browser.show();
browser.show();
browser.show();
browser.show();
browser.show();
}
}
- 매번 새로운 Html이 loading 된다
02. Cache 기능 추가
- Cache는 브라우저에서 지원을 해줘야한다
- BrowserProxy.java
package com.company.design.proxy;
public class BrowserProxy implements IBrowser{
private String url;
private Html html;
public BrowserProxy(String url) {
this.url = url;
}
@Override
public Html show() {
if(html == null) {
this.html = new Html(url);
System.out.println("BrowserProxy loading html from : " + url);
}
System.out.println("BrowserProxy use cache html "+ url);
return html;
}
}
package com.company.design;
import com.company.design.proxy.Browser;
import com.company.design.proxy.BrowserProxy;
import com.company.design.proxy.IBrowser;
public class Main {
public static void main(String[] args) {
/*
Browser browser = new Browser("www.naver.com");
browser.show();
browser.show();
browser.show();
browser.show();
browser.show();
*/
IBrowser browser = new BrowserProxy("www.naver.com");
browser.show();
browser.show();
browser.show();
browser.show();
browser.show();
}
}
03. AOP(Aspect Oriented Programming, 관점 지향 프로그래밍)
- 특정한 메소드가 있으면 메소드의 실행 시간이라던지 또는 특정한 패키지의 특정한 메소드들의 실행시간 또는 전후 작업하고 싶은 부분들
- 일괄적으로 특정한 요청에 대해서 request 정보를 남긴다던지 response 정보를 담긴다던지 코드에 다가 개별적으로 하는게 아닌 일괄적으로 특정 패키지에 모든 메소드들을 이런 형식으로 전후에 기능을 넣을 수 있는 부분
- 특정 메소드가 얼마나 시간이 걸렸는지, 시스템에서 특정 메소드가 시간이 얼마나 걸리는지 측정할 때도 사용
-1. Proxy로 AOP 구성
- Package : aop
- Class : AopBrowser
- AopBrowser.java
package com.company.design.apo;
import com.company.design.proxy.Html;
import com.company.design.proxy.IBrowser;
public class AopBrowser implements IBrowser {
private String url;
private Html html;
// 앞과 뒤 체크를 위한 @FunctionalInterface
// run() 추상 메소드를 가지고 있다, 람다식으로 표현 가능
private Runnable before;
private Runnable after;
public AopBrowser(String url, Runnable before, Runnable after) {
this.url = url;
this.before = before;
this.after = after;
}
@Override
public Html show() {
before.run();
if(html == null) {
html = new Html(url);
System.out.println("AopBrowser html loading from " + url);
// 메소드가 빠를 수 있기에 조금의 틈을 준다
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
after.run();
System.out.println("AopBrowser html cache " + url);
return html;
}
}
package com.company.design;
import com.company.design.apo.AopBrowser;
import com.company.design.proxy.Browser;
import com.company.design.proxy.BrowserProxy;
import com.company.design.proxy.IBrowser;
import java.util.concurrent.atomic.AtomicLong;
public class Main {
public static void main(String[] args) {
/*
Browser browser = new Browser("www.naver.com");
browser.show();
browser.show();
browser.show();
browser.show();
browser.show();
IBrowser browser = new BrowserProxy("www.naver.com");
browser.show();
browser.show();
browser.show();
browser.show();
browser.show();
*/
// 시간 체크, 동시성 문제로 AtomicLong을 사용
AtomicLong start = new AtomicLong();
AtomicLong end = new AtomicLong();
IBrowser aopBrowser = new AopBrowser("www.naver.com",
()->{
System.out.println("before");
start.set(System.currentTimeMillis());
},
()->{
long now = System.currentTimeMillis();
end.set(now - start.get());
});
aopBrowser.show();
System.out.println("loading time : " + end.get());
aopBrowser.show();
System.out.println("loading time : " + end.get());
}
}