대리인
뭔가 대신해서 처리
Proxy Class를 통해 대신 전달하는 형태가 설계되고, Client는 Proxy로부터 전달된 결과를 받음
Cache 기능으로 활용 가능
SOLID 중 개방 폐쇄 원칙(OCP), 의존 역전 원칙(DIP)
앞 뒤로 넘어가는 기능, 인자 값 조절 가능
흩어져있는 공통된 기능(공통된 method)을 하나로 묶어줄 수 있음
브라우저는 매번 새로운 url 로딩, 새롭게 생성된 html 파일을 return 하는 일을 함
반복되는 이 기능을 프록시가 중간(Browser - Clinet)에서 대신 처리
public interface IBrowser {
HTML show();
}
public class Browser implements IBrowser {
private String url;
public Browser(String url) {
this.url = url;
}
// 브라우저가 어떤 페이지 동작 시, 매번 새로운 url 을 로딩하고, 새롭게 생성된 해당 HTML 파일을 return
@Override
public HTML show() {
System.out.println("browser loading html from: " + url);
return new HTML(url);
}
}
// Cache 기능을 갖는 Proxy Pattern
public class BrowserProxy implements IBrowser{
private String url;
private HTML html;
public BrowserProxy(String url) {
this.url = url;
}
@Override
public HTML show() {
// Cache
if(html == null) {
// HTML 에 url 데이터가 없다면, 새롭게 url 을 생성해서 브라우저에 반환
this.html = new HTML(url);
System.out.println("BrowserProxy loading html from: " + url);
}
// HTML 에 url 데이터가 있다면, 기존에 저장된 url 을 반환 -> Cache
System.out.println("BrowserProxy use cache html: " + url);
return html;
}
}
public class HTML {
private String url;
public HTML(String url) {
this.url = url;
}
}
// Browser browser = new Browser("www.naver.com");
// browser.show(); 를 할때마다, url 이 새롭게 계속 할당(loading)되므로 비효율적
// Proxy 를 통해서, Cache(캐시) 를 만들어 url 저장
IBrowser browser1 = new BrowserProxy("www.naver.com");
browser1.show(); // 한번만 loading
browser1.show(); // 동일한 url 은 cache 사용
browser1.show();
browser1.show();
browser1.show();
// aop : 특정 패키지에 포함된 모든 method 를 일괄적으로 구현
/* Aop method 특징
- 기본적으로 before, after method 가 있음
- 관점지향, 일괄적적 */
public class AopBrowser implements IBrowser {
private String url;
private HTML html;
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(); // html loading time
if(html == null) {
this.html = new HTML(url);
System.out.println("AopBrowser html loading from : " + url);
try {
// method 실행 시간이 너무 짧을 수 있어서 sleep()
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
after.run(); // html loading time
System.out.println("AopBrowser html cache : " + url);
return html;
}
}
// Proxy 를 통해서, Aop 기능 구현
// 시간 method 는 동시성 문제때문에 atomic 사용
AtomicLong start = new AtomicLong();
AtomicLong end = new AtomicLong();
// Aop 기능 람다식으로 표현
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()); // 1.5초 + 실행 시간
aopBrowser.show();
System.out.println("loading time2 : " + end.get()); // cache 를 사용해서 0초