Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can the proxy pattern be used to replace a singleton?

This is in response to some comments in what is so bad about singletons

There it was suggested that the proxy pattern can be used instead of a singleton to cache DB data. But I cannot see the advantage, and in fact the singleton seems more "controllable".

Let me elaborate on the problem. Assume you have a database, with a large set of data, that never changes so it can be regarded read only, why would the proxy pattern be a better way of modelling this data cache than the singleton?

(PS: if you are going to say "because its more 'testable' !" - please elaborate, I am still getting used to those concepts)

Thanks for your help!

like image 905
Dai Bok Avatar asked Jan 19 '10 15:01

Dai Bok


People also ask

What is the main purpose of the proxy pattern?

Proxy pattern is used when we need to create a wrapper to cover the main object's complexity from the client. Remote proxy: They are responsible for representing the object located remotely. Talking to the real object might involve marshalling and unmarshalling of data and talking to the remote object.

How can singleton pattern be avoided?

There are many ways to prevent Singleton pattern from Reflection API, but one of the best solutions is to throw a run-time exception in the constructor if the instance already exists. In this, we can not able to create a second instance.

What problems does the proxy pattern solve?

The Proxy design pattern is one of the twenty-three well-known GoF design patterns that describe how to solve recurring design problems to design flexible and reusable object-oriented software, that is, objects that are easier to implement, change, test, and reuse.

What is the use of proxy design pattern in java?

Proxy design pattern common uses are to control access or to provide a wrapper implementation for better performance. Java RMI package uses proxy pattern. That's all for proxy design pattern in java.


2 Answers

disclaimer: I'm speaking in java terms here

singleton are now considered an antipattern mostly because have been abused a lot lately as they are a quick and convenient way to share data across the application - which is somewhat an overextension of the design pattern which is more suited to provide acces control to a shared resource.

consider a program standard output: the access of that resource needs to be guarded by a single point of access to allow for synchronization of the writes, that is why you have for example System.out as a static instance in java.

the problem is, when you start having singleton you'll need to know every nitty gritty details of what you're doing, because you are making lot of strict assumption on your singleton class, the most important one that it will be the only one class in the system. then you start using it, assuming that it will always be a single entry point to your resource, and then nasty bug arises because your class has now been deployed on an ejb server and each ejb context has it's own singleton, plus one more singleton for every jsp that has been reloaded from the server, plus one singleton for every time that your singleton has been serialized and deserialized (as you probably have forgot to override readResolve() method).

so this is why singleton have to be used with lot of care, and are now considered an antipattern in spite of them being totally useful for their intended usage.

in the case of a database cache, it would be a better approach to have each class in need of the cache using a proxy for this "cache" resource, so you may add the logic to "find the resource" within the proxy itself instead of having the logic be tied to the retrieval of the cache singleton, which may or may not work depending on the environment.

so in few words using singleton as means to have a shared access to a resource is bad, because you are hardcoding the method of finding the resource (and ignoring the singleton pitfalls) while having singleton to control a resource for synchronization purpose is totally acceptable.

think of semaphores, those works only if you can get the same semaphore always. in this latter case what may be a problem is accessing the singleton from everywhere you need to access that semaphore: here you'll need some class to wrap the singleton up and provide a finer control of the lifecycle of the semaphore itself.

proxy are intended to cover the role of "providing a resource across the system", be it a single application, a client server system, different components of the same system and so on, with the added benefit that with èrpxy the method of retrieval of the resource is opaque. you may have them providing you a singleton containing an hashmap of the cached values, you may have them accessing a memcached somwhere on the network, you may have them reading a csv during tests, all without changing how you call them from the application.

like image 144
Lorenzo Boccaccia Avatar answered Oct 26 '22 23:10

Lorenzo Boccaccia


In my opinion, there is no "either, or". A class can implement several design patterns at the same time. I would say the class implementing the access to the external database is in any case a Proxy (a remote proxy in this case). If you consider the caching an extra functionality it is also a Decorator.

So, the real question is, should it also be a Singleton? Let us assume there is exactly one external database. Does there need to be only one CachingDBProxy? I would say, it depends on the use:

If there are several clients accessing similar data, they can clearly benefit if they share the same CachingDBProxy. The data needed by one client may already have been needed by another client, so it can be retrieved from the cache instead of having to perform a costly access to the database.

On the other hand, some clients may access quite distinct pieces of data. So, if we assume that the CachingDBProxy only caches a limited amount of data access by one group of clients may throw out data still needed by another group of clients, causing degradation of cache performance. In this case it may be reasonable to have multiple CachingDBProxies even though there is only one database (this assumes of course, that concurrent access is possible).

So, how many CachingDBProxies there should be, depends on the use. The CachingDBProxy should not limit its use without good reason, so it should not enforce that there is only one instance, So, in this case the CachingDBProxies should be no Singleton, IMHO. Only the clients can know how many CachingDBProxies are good for them.

On the other hand, if we have a Proxy for specific resource that can only handle one access at a time, it may have to be a Singleton. But that is a distinct case from the above case. Here the requirement comes directly from the area the Proxy is responsible for (its purpose is to channel the access to that specific resource).

like image 20
lwho Avatar answered Oct 26 '22 23:10

lwho