Active Object Design Pattern in Delphi (Part 4): The Servant and the Proxy
In this blog post I will continue to describe the process to develop a solution in Delphi using the Active Object Design Pattern. Specifically, we will see how the Proxy composes and uses a Scheduler and a Servant
If you missed Part 1: Method Requests, Part 2: The Scheduler or Part 3: Futures. I would recommend that you read those first before proceeding.
In the fourth part of the deep dive into the Active Object pattern I want to look at how we put the pieces together to create a Proxy for a Servant object. First a few guidelines given by the pattern:
- The Servant does not do synchronization, it is unaware of the Scheduler and the Proxy
- The Client should be able to use the Proxy in the same or similar way to the Servant (except for Futures)
- The Client and Proxy operate in the Client’s thread, the Scheduler and Servant operate in the Scheduler’s thread
The Servant is an ordinary object that holds the implementation or functions of the work and data that need to grouped together. If we are using the Active Object Pattern to retrofit an existing system, the Servant would be your current non-threaded object that you would want to be running in its own thread.
The Proxy presents the same or a very similar interface to the Client as the Servant would have. This allows us to retrofit our code to use an object that runs in its own thread without any special synchronization code in the Client. The Proxy typically internally constructs the Servant as well as the Scheduler and would enqueue methods intended for the servant
Here is an example of a Servant that provides methods put_i
, get_i
, empty_i
and full_i
. The naming was chosen to match the sample provided in Lavender and Schmidt’s Paper. The message type (here called TMessage
) is immaterial to the demonstration. Assume that it is communication that gets placed or read from the queue.
I won’t cover TServant
’s implementation because it simply enqueues and dequeues in a simple queue. It has no synchronization knowledge and does not need to have any special code to be thread safe or deal with concurrency.
The proxy will present a similar interface as the Servant. I assume that the sample in the paper used *_i
for methods of the Servant to distinguish those in the Proxy that are named without the _i
(perhaps meaning “internal”). However, in a real example the Proxy may actually follow the “Decorator” pattern or implement the same interface(s) as the Servant.
The Proxy composes the Servant and the Scheduler as follows
And the implementation would look like the sample we saw in Part 1: Method Requests. Our put
and get
are converted to Method Requests and enqueued with the Scheduler.
This concludes the series on the Active Object pattern. I hope you found it useful. You can download the source code. Please comment or contribute.
Leave a Comment