Proxy
Proxy
프록시 패턴은 특정 객체에 대한 접근을 제어하거나 기능을 추가 할 수 있는 패턴을 의미한다.
부가 기능 추가가 목적인 Proxy 패턴을 Decorator 패턴이라고 한다.
- Subject: This is the interface or abstract class that defines the operations that the real object and the proxy must implement.
- RealSubject: This is the real object that the proxy represents. It implements the operations defined in the subject interface.
- Proxy: This is the object that acts as a surrogate or placeholder for the real object. It implements the subject interface and delegates the operations to the real object.
코드로 보면 다음과 같다.
Subject:
interface Subject {
fun doSomething(): Void
}
Real Subject:
class RealSubject: Subject {
override fun doSomething() {
// doSomething
}
}
Proxy class:
class Proxy: Subject {
private val realSubject = RealSubject()
override fun doSomething(): Void {
// doSomething (caching, logging ...
return realSubject.doSomething() // delegation
}
}
이러한 방식으로 구현해서 사용하면 된다.
Remote Proxy
원격 프록시(Remote Proxy)는 프록시는 로컬에 있고, RealSubject 가 원격 서버(다른 서버)에 존재하는 경우 사용할 수 있다. 프록시는 네트워크 통신을 통해 클라이언트 요청을 RealSubject 로 전달한다.
Subjects:
interface ProductService {
fun getProducts(): List<Product>
}
Next, we define the real subject class that implements the ProductService interface and fetches the list of products over the network:
class RemoteProductService : ProductService {
override fun getProducts(): List<Product> {
// Fetch products over the network
Thread.sleep(5000) // Simulate network delay
return listOf(Product("Product 1"), Product("Product 2"), Product("Product 3"))
}
}
data class Product(val name: String)
Now, we define the remote proxy class that implements the ProductService interface and delegates the operations to the real subject class:
class RemoteProductServiceProxy : ProductService {
private val realService = RemoteProductService()
override fun getProducts(): List<Product> {
// Check if the list of products is already cached
// If yes, return the cached list
// Otherwise, fetch the list from the remote service
return realService.getProducts()
}
}
Finally, we can use the remote proxy to fetch the list of products without incurring the overhead of network communication:
fun main() {
val productService: ProductService = RemoteProductServiceProxy()
// Fetch the list of products
val products = productService.getProducts()
// Print the list of products
println("Products:")
products.forEach { println(it.name) }
}
Virtual Proxy
객체 생성 작업이 무거울때 사용하는 Lazy Initialization 방식
First, we define the subject interface that defines the operations for loading and displaying the image:
interface Image {
fun display()
}
Next, we define the real subject class that implements the Image interface and loads the actual image:
class RealImage(private val filename: String) : Image {
init {
loadFromDisk()
}
private fun loadFromDisk() {
// Load the image from the disk
println("Loading image from disk: $filename")
}
override fun display() {
// Display the image
println("Displaying image: $filename")
}
}
Now, we define the virtual proxy class that implements the Image interface and creates the real subject object only when it is needed:
class VirtualImage(private val filename: String) : Image {
private var realImage: RealImage? = null
override fun display() {
// Create the real image object only when it is needed
if (realImage == null) {
realImage = RealImage(filename)
}
// Display the image
realImage?.display()
}
}
Protection Proxy
보호 프록시의 목적은 접근 권한을 제어하는 것이다.
First, we define the subject interface that defines the operations for accessing the information:
interface InformationService {
fun getInformation(): String
}
Next, we define the real subject class that implements the InformationService interface and provides access to the sensitive information:
class RealInformationService : InformationService {
override fun getInformation(): String {
return "Sensitive information"
}
}
Now, we define the protection proxy class that implements the InformationService interface and checks the permissions before granting access to the sensitive information:
class ProtectionInformationService(private val informationService: InformationService, private val user: String) : InformationService {
override fun getInformation(): String {
// Check if the user has the proper permissions
if (user == "admin") {
// Grant access to the sensitive information
return informationService.getInformation()
} else {
// Deny access to the sensitive information
throw SecurityException("Access denied")
}
}
}
Finally, we can use the protection proxy to restrict access to the sensitive information:
fun main() {
// Create the real subject object
val realService: InformationService = RealInformationService()
// Create a protection proxy for the information service
val informationService: InformationService = ProtectionInformationService(realService, "admin")
// Get the sensitive information
val information = informationService.getInformation()
// Print the sensitive information
println("Information: $information")
}