Name: Proxy Type: Structural
The Proxy design pattern is a structural pattern that provides an in-between, or placeholder for another object. They are closely related in structure, to Adapters and Decorators but they have different purposes.
The Proxy design pattern can be used in a variety of scenarios, but its goal is generally to preserve exactly (or as closely as possible) the API that is being used while offering certain internal enhancements.
It's useful when we want to add a layer of control over the interaction with an object. In the context of C#, implementing the Proxy pattern involves creating a proxy class that wraps an object and controls access to it.
Imagine you are at a restaurant that has a limited number of tables. The restaurant has a hostess who stands at the door and checks if there is a table available before seating a customer. The hostess acts as a proxy for the tables. She controls access to the tables and chairs and ensures that the tables are distributed as best as possible.
Another example we often encounter in real life is when we order coffee. When we want to order a coffee, we don't go directly to the barista behind the counter or make it ourselves. Instead, we place the order with a person, who then relays the order to the barista. The person taking our order acts as a proxy for us, handling the communication and coordination between us and the barista.
For the proxy design pattern, we have three main entities involved.
You can see in the diagram below the interaction between classes.
For our example implementation we have the following components:
IOrderService
interface represents the service interface for placing food orders.RestaurantKitchen
class is the real subject that prepares the food. This is the actual code that we want to interact with.Waiter
class acts as a proxy for the RestaurantKitchen
. When a client wants to place an order, the waiter can perform various tasks (like confirming the order, checking special requests, etc.) before delegating the actual food preparation to the RestaurantKitchen
.IOrderService
interface and uses the Waiter
to place orders. The client is unaware of the direct interaction with the RestaurantKitchen
which illustrates the encapsulation provided by the Proxy pattern.This design allows for additional logic and features to be implemented in the Waiter
without modifying the underlying RestaurantKitchen
or the client's code.
// Service Interface
public interface IOrderService
{
void PlaceOrder(string dish);
}
// Real Subject
public class RestaurantKitchen : IOrderService
{
public void PlaceOrder(string dish)
{
Console.WriteLine($"Cooking {dish} in the kitchen.");
}
}
public class Waiter : IOrderService
{
private RestaurantKitchen _kitchen;
public Waiter(RestaurantKitchen kitchen)
{
_kitchen = kitchen;
}
public void PlaceOrder(string dish)
{
Console.WriteLine($"Waiter is taking order for {dish}.");
// Additional checks or preparations can be done here.
_kitchen.PlaceOrder(dish);
}
}
Control Access: The proxy can control access to the real subject(RestaurantKitchen
), which is useful for lazy initialization, permissions, etc.
Additional Functionality: You can add additional functionality (e.g., caching, logging, monitoring) before/after the request to the real subject.
Open/Closed Principle: You can introduce new proxies without changing the subject or client
The Proxy Design Pattern stands out as it does not conform to a single, uniform structure. There is a wide variety of proxy types that serve distinct functions. The choice of which one to implement depends on the specific requirements of the software design problem at hand. Below there are just a few of them:
Each of these proxy types serves a different purpose, and the choice of which one to implement depends on the specific requirements of the software design problem at hand.
In essence, the Proxy design pattern is a powerful tool that can take many forms. It doesn’t try to expand the public API surface of an object by adding new members but it can control access and add supplementary behavior to objects without changing the object's code or the client's code.
P.S. Want the source code or level up your coding? Consider joining my monthly newsletter. Sign up here!
Hi! Welcome to my blog