Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- QueryDSL
- http
- 스프링 핵심 기능
- kotlin
- Android
- SpringBoot
- Spring Boot
- Proxy
- 스프링 핵심 원리
- pointcut
- java
- db
- 인프런
- 백준
- JDBC
- Servlet
- transaction
- 김영한
- Thymeleaf
- 그리디
- AOP
- 자바
- JPQL
- 알고리즘
- springdatajpa
- jpa
- Exception
- Greedy
- 스프링
- spring
Archives
- Today
- Total
개발자되기 프로젝트
낭비를 없애기 - Proxy Pattern 본문
1.Proxy Pattern
- 객체에 대한 접근을 제어하기 위해 대리자를 둔다.
2. 의도와 동기
- 어떤 객체가 생성에 초기화 비용이 많이 들거나 복잡한 경우 간단한 처리는 대리자를 통해 하게된다.
- 실제적으로 비용이 많이 들어가는 처리일 때 객체를 만들도록 한다.
3. 객체 종류
- 원격지 프록시(remote proxy) : 서로 다른 주소 공간에 존재하는 객체를 대리하는 로컬 객체
- 가상 프록시(virtual proxy): 고비용의 객체는 필요한 경우만 생성
- 보호용 프록시(protextion proxy) : 실제 객체에 대한 접근 권한을 제어하기 위한 경우 사용.
4. 객체 협력 (collaborations)
- Proxy
- 실제 참조할 대상을 관리
- 실제 객체와 동일한 메서드 제공
- 클라이언트에게 먼저 노출되는 객체
- RealSubject
- 프록시가 대리하는 실제 객체
- Subject
- Proxy와 Real의 공통 메서드 선언
5. 중요한 결론 (consequence)
- 프록시 패턴은 객체에 접근하는데 보호, 가상등의 역할을 한다.
6. 예제
- 주어진 string을 출력하는 프린터 클래스가 있다.
- 프린터 인스턴스 생성에는 5초가 소요된다.
- PrinterProxy는 print()를 호출 시점에 Printer 인스턴스가 없으면 Printer 인스턴스를 생성한다.
- 나머지 메서드는 Printer 인스턴스가 없어도 proxy에서 처리함.
public interface Printable {
public String getPrinterName();
public void setPrinterName(String name) ;
public void print(String string);
}
- 프린터 인스턴스 생성에 5초가 걸린다.
public class Printer implements Printable{
String name;
public Printer() {
heavyJob("Printer 인스턴스 생성 중...");
}
public Printer(String name) {
this.name = name;
heavyJob("Printer 인스턴스 생성 중...");
}
private void heavyJob(String message) {
System.out.println(message);
for (int i=0; i<5; i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(".");
}
System.out.println("complete");
}
@Override
public String getPrinterName() {
//나는 진짜 object다..
System.out.println("real : getName()");
return name;
}
@Override
public void setPrinterName(String name) {
System.out.println("real : setName()");
this.name = name;
}
@Override
public void print(String string) {
System.out.println("==== "+ name+ " ====");
System.out.println(string);
}
}
- PrinterProxy는 Printer객체 앞에서 Printer 객체 대신에 몇몇 기능을 대신한다.
- 다만 Print()메서드는 진짜 Printer 객체에서 처리할 수 있기 때문에, 해당 메서드 호출 시점에 Printer 인스턴스가 없으면 새로 생성한다.
- 프린터 인스턴스 생성에 5초가 걸린다.
- 따라서 realize() 진행 중 다른 Thread에서 Printer resource에 접근하지 못하도록 막음.
public class PrinterProxy implements Printable{
private String name;
private Printer real; //real object
public PrinterProxy() {
}
public PrinterProxy(String name) {
this.name = name;
}
@Override
public String getPrinterName() {
System.out.println("proxy : getName()");
return name;
}
@Override
public void setPrinterName(String name) {
if (real != null){
real.setPrinterName(name);
}
else {
System.out.println("proxy : setName()");
this.name = name;
}
}
@Override
public void print(String string) {
realize();
real.print(string);
}
//5초 지연을 줄건데, 그 동안에 interrupt 들어오면 안됨! 멈춰!
public synchronized void realize() {
if (real == null){
real = new Printer(name);
}
}
}
public class Main {
public static void main(String[] args) {
Printable p = new PrinterProxy("Alice");
System.out.println("현재의 이름은 " + p.getPrinterName() + " 입니다.");
p.setPrinterName("Bob");
p.print("test~");
p.print("hello~");
p.setPrinterName("tomas");
p.print("world");
}
}
proxy : getName()
현재의 이름은 Alice 입니다.
proxy : setName()
Printer 인스턴스 생성 중...
.
.
.
.
.
complete
==== Bob ====
test~
==== Bob ====
hello~
real : setName()
==== tomas ====
world
- 이처럼 client입장에서 proxy인지 real object인지 모르고 사용하기 때문에 proxy객체를 통해,
- 자원이 많이 소모되는 인스턴스 생성을 최대한 늦출 수 있는 장점이 있고,
- real object 앞에서 real object 처럼 사용되기 때문에 real object에 대한 보호 기능도 할 수 있다.
7. GitHub : 211115 proxy pattern
'Java > 디자인 패턴' 카테고리의 다른 글
해석 - Interpreter Pattern (0) | 2021.11.17 |
---|---|
명령 - Command Pattern (0) | 2021.11.15 |
낭비를 없애기 - Flyweight Pattern (0) | 2021.11.15 |
구조 안을 돌아다니며 처리 - Chain of Responsibility (0) | 2021.11.15 |
구조 안을 돌아다니며 처리 - Visitor (0) | 2021.11.13 |
Comments