일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Spring
- java
- Adapater Pattern
- springboot
- 자바의 정석
- programmers
- 17장
- 2156번
- SerialDate 리펙터링
- java의 정석
- 1043번
- 가장 긴 증가하는 부분 수열2
- 코딩 테스트
- 2206번
- DxTrace
- BOJ
- Design Patterns
- Design Pattern
- Dxerr.h
- 11286번
- 11758번
- 코딩테스트
- 10830번
- 냄새와 휴리스틱
- 프로그래머스
- 클린코드
- 9장
- 백준
- 2166번
- 1300번
- Today
- Total
Don't give up!
[Design Pattern] 프록시 패턴(Proxy Pattern) 본문
[Design Pattern] 프록시 패턴(Proxy Pattern)
Heang Lee 2021. 12. 26. 22:53이 글은 에릭 프리먼의 'Head First Design Patterns'를 읽고 TIL(Today I Learned)로써 정리한 내용을 기록하는 글입니다.
자세한 내용은 책을 통해 확인하실 수 있습니다.
알라딘: Head First Design Patterns (aladin.co.kr)
프록시 패턴 (Proxy Pattern)
프록시 패턴은 객체에 대한 접근을 제어하기 위해 대리인이나 대변인에 해당하는 객체를 제공하는 패턴입니다.
객체를 사용하고자 할 때, 직접적으로 객체를 참조하지 않고 Proxy 객체를 통해 대상 객체에 접근함으로써 객체가 클라이언트의 힙에 존재하지 않아도 제어할 수 있습니다.
프록시 패턴은 다음의 종류가 존재합니다.
- 원격 프록시(Remote Proxy) : 다른 JVM에 들어있는 객체에 대한 접근을 제어할 수 있도록 합니다.
- 가상 프록시(Virtual Proxy) : 진짜 객체가 생성되기 전까지 해당 객체를 대신함으로써 생성하기 힘든 자원에 대한 접근을 제어할 수 있습니다.
- 보호 프록시(Access Proxy) : 접근 권한이 필요한 자원에 대한 접근을 제어할 수 있습니다.
- 방화벽 프록시 : 네트워크 자원에 대한 접근을 제어합니다.
- 스마트 레퍼런스 프록시(Smart Reference Proxy) : 주 객체가 참조될 때마다 추가 행동을 제공합니다.
- 캐싱 프록시(Caching Proxy) : 비용이 많이 드는 작업의 결과를 임시 저장합니다. 여러 클라이언트에서 결과를 공유하게 함으로써 계산 시간 또는 네트워크 지연을 줄여주는 효과가 있습니다.
- 동기화 프록시(Synchronization Proxy) : 여러 스레드에서 객체에 접근하는 경우에 작업을 처리할 수 있게 합니다.
- 복잡도 숨김 프록시(Complexity Hiding Proxy) : 복잡한 클래스 집합에 대한 접근을 제어하고, 복잡도를 숨깁니다.
- 지연 복사 프록시(Copy-On-Write Proxy) : 클라이언트에서 필요로 할 때까지 객체가 복사되는 것을 지연시킴으로써 객체의 복사를 제어합니다.
자바의 동적 프록시(Java Dynamic Proxy)
자바의 java.lang.reflect 패키지에는 Proxy 클래스가 내장되어 있습니다.
Proxy 클래스의 기능들을 활용하면 실행 중에 프록시 객체를 생성할 수 있으며 이러한 자바 기술을 동적 프록시(dynamic proxy)라고 합니다.
다음은 동적 프록시를 사용하여 구현한 보호 프록시의 코드입니다.
//subject 인터페이스
public interface PersonBean {
String getName();
String getGender();
String getInterests();
int getHotOrNotRating();
void setName(String name);
void setGender(String gender);
void setInterests(String interests);
void setHotOrNotRadting(int rating);
}
//실제 subject 클래스
public class PersonBeanImpl implements PersonBean {
String name;
String gender;
String interests;
int rating;
int ratingCount = 0;
public String getName() {
return name;
}
public String getGender() {
return interests;
}
public in getHotOrNotRating() {
if (ratingCount == 0) return 0;
return (rating / ratingCount);
}
public void setName(String name) {
this.name = name;
}
public void setGender(String gender) {
this.gender = gender;
}
public void setInterests(String interests) {
this.interests = interests;
}
public void setHotOrNotRating(int rating) {
this.rating += rating;
ratingCount++;
}
}
//java.lang.reflect 패키지에서 제공하는 InvocationHandler 인터페이스를 구현하여 proxy를 생성하는 핸들러 구현
public class OwnerInvocationHandler implements InvocationHandler {
PersonBean person;
public OwnerInvocationHandler(PersonBean person) {
this.person = person;
}
public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException {
try {
if (method.getName().startsWith("get")) {
return method.invoke(person, args);
} else if (method.getName().equals("setHotOrNotRating")) {
throw new IllegalAccessException();
} else if (method.getName().startsWith("set")) {
return method.invoke(person, args);
}
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
//프록시를 활용하는 클라이언트 클래스
public class MatchMakingTestDrive {
public static void main(String[] args) {
MatchMakingTestDrive test = new MatchMakingTestDrive();
test.drive();
}
public MatchMakingTestDrive() {
initializeDatabase();
}
public void drive() {
PersonBean joe = getPersonFromDatabase("Joe Javabean");
PersonBean ownerProxy = getOwnerProxy(joe);
System.out.println("Name is " + ownerProxy.getName());
ownerProxy.setInterests("bowling, Go");
System.out.println("Interests set from owner proxy");
try {
ownerProxy.setHotOrNotRating(10);
} catch (Exception e) {
System.out.println("Can't set rating from owner proxy");
}
System.out.println("Rating is " + ownerProxy.getHotOrNotRating());
}
//subject의 classloader, subject의 interface, 그리고 subject의 InvoactionHadler 객체를 인자로 하여 프록시 객체를 생성하는 Proxy의 newProxyInstance 메소드
PersonBean getOwnerProxy(PersonBean person) {
return (PersonBean) Proxy.newProxyInstance(
person.getClass().getClassLoader(),
person.getClass().getInterfaces(),
new OwnerInvocationHandler(person));
}
}
'개발서적 > Head First Design Patterns' 카테고리의 다른 글
[Design Pattern] 컴파운드 패턴 (Compound Pattern)과 MVC 패턴(Model-View-Controller Pattern) (0) | 2022.01.02 |
---|---|
[Design Pattern] 상태 패턴 (State Pattern) (0) | 2021.12.24 |
[Design Pattern] 컴포지트 패턴(Composite Pattern) (0) | 2021.12.22 |