Introduction
Previously, in the blog Implementing Lazy Loading with Proxy Design Pattern, I discussed about Proxy Pattern, in particular Remote Proxy. Lazy loading benefit and Fast Compiling are demonstrated. Various considerations are needed to implement the pattern with C++.
Kotlin and C# provides a new concept and implementation: Delegate which helps creating more concise program.
In this blog, I discuss Delegate concept, Proxy pattern, re-cap the consideration needed to implement the pattern with C++. Finally I will provide implementation code with Kotlin.
Concepts
Delegation
A delegate is a type that represents a reference to a method(s). It allows user to call a function with defined signature via another entity.
- For C#, "a delegate is a type that represents references to methods with a particular parameter list and return type. When you instantiate a delegate, you can associate its instance with any method with a compatible signature and return type. You can invoke (or call) the method through the delegate instance. Delegates are used to pass methods as arguments to other methods"
- A delegate is similar to function pointer, but unlike C++, a delegate "encapsulates both an object instance and a method"
- For Kotlin, a delegate properties is declared as a property inside a class. The property has the type of the remote class that we need to invoke methods.
- Kotlin delegate properties have built-in implementation that support various features. They are Lazy delegate, Observable delegate, and Storing delegate.
Proxy Pattern
A proxy pattern refers to design that allows client to call functions of a service class via a proxy class. There are different types of proxies:
- Remote Proxy: data could be stored to local storage by proxy class.
- Virtual Proxy: provides lazy loading. Real service class is only initialized once, when needed by the proxy class.
- Protection Proxy: access to the service class is restricted and controlled by the proxy class
C++ Virtual Proxy implementation
Detail implementation of Virtual Proxy pattern was described in this blog post. Here are some re-caps:
- There is an
interfacethat abstracts the functions to be called by clients Service classimplements the interface and the functions.Proxy classimplements the interface and the functions. The service class has either aggregation or composition relationship with the Service class.- Proxy class has a pointer to Service class. The pointer is initially null. This is required for safe initialization of pointer.
- Proxy class initializes Service when the client invokes requested functions for the first time.
- Proxy class checks if the pointer to Service class is null or not.
- When the client requests service, the proxy invokes the requested function via Proxy class.
- Proxy class can use function pointer to invoke Real class's function.
- When Proxy class is deleted, it also deletes the instance of Service class, and assigns the member pointer to Service class to null. This is required for safe delete of pointer.
- Client has to initialize the Proxy Class.
Kotlin Proxy implementation
Implement basic delegate to route request to service class.
Similar to C++, Kotlin implementation of Proxy Pattern requires an interface, a proxy class and a service class.
However, since Kotlin is designed to be concise, (short and clear), we don't need to implement complicating constructor, destructor, null pointer checking, pointer initialization etc. Instead, by keyword is sufficient.
- Lazy property: the value is computed only on first access
lazy()is a function that takes a lambda and returns an instance ofLazy<T>, which can serve as a delegate for implementing a lazy property.- The first call to
get()executes the lambda passed tolazy()and remembers the result. - Subsequent calls to
get()simply return the remembered result [1]
- The first call to
Client has to create an instance of Real class and Proxy Class. The instance of Real class is passed to the Proxy Class.
// Define the interface
interface DataService {
fun loadData()
}
// Implement the interface in the Data class
class Data : DataService {
override fun loadData() {
println("Loading data...")
// Implementation logic goes here
}
}
// Implement the DataProxy class with the delegate keyword
class DataProxy(private val delegate: DataService) : DataService by delegate
fun main() {
val data = Data()
val dataProxy = DataProxy(data)
dataProxy.loadData()
}
Implement Lazy Delegate
The above program is modified so that the Data class is initialized only once, the first time when loadData function is called by client.

We can implement that by removing the constructor in the DataProxy class and instead define a lazy delegate property inside the DataProxy class
// Define the interface
interface DataService {
fun loadData()
}
// Implement the interface in the Data class
class Data : DataService {
override fun loadData() {
println("Loading data...")
// Implementation logic goes here
}
}
// Remove DataProxy constructor that includes delegate
// class DataProxy(private val delegate: DataService) : DataService by delegate
// Implement the DataService interface in the DataProxy class using delegation with lazy initialization
class DataProxy : DataService {
private val data: DataService by lazy {
println("Data is initialized")
Data()
}
override fun loadData() {
data.loadData()
}
}
fun main() {
val dataProxy = DataProxy()
println("Before calling loadData")
dataProxy.loadData() // Creates an instance of Data and calls loadData
println("After calling loadData")
dataProxy.loadData() // Reuses the previously created instance of Data and calls loadData again
}
The output indicates that Data instance is only called once:
Before calling loadData
Data is initialized
Loading data...
After calling loadData
Loading data...
References
[1] Delegated properties | Kotlin Documentation (kotlinlang.org)