This is in the paradigm of client-server programming, such as the developer project. there may be multiple clients making requests to the server. To provide consistent & accurate (at least the moment of response of the server) information to the clients, server must provide a means of uniqueness of information. The locking mechanism is one of the methods that serves this uniqueness, if not the only one. To make this locking work, we must ensure the singleton object which the mechanism locks on.
1. The ultimate uniqueness is from the existence of the single copy of the data. At this bottom level, multiple data object is allowed (multiton architecture). However, each server operation must be processed at the lower level of data file io. external resources may require to ensure that only one operation on the physical data file at a time.
2. the next upper level is to make the file handler/descriptor singleton in the program. server operations still required to read/write to the datafile but is better than 1 since we can keep file open. so the performance is better. (if one wraps his file io into a class and make this class singleton, this is equivalent).
3. for better performance, we are used to employ cache (in-memory) technique. This also provides another upper layer of singleton that locking can place. (I use cache.) Not all server operations require low-level file ops. For example, a non-critical readRecord can simply look at cached Record, rather than the data on disc file. Also, this provides a finer locking possibility at the record level.
4. simply make the data object singleton. I think this is the easiest. It has quite similar result as 3, except no record-level locking. At this level, the data object singleton is made in the adaptor, rather than below the level of Sun's designated interface. This may be a potential hole, at least in testing: a separate program can bypass the singleton obligation and render the locking mechanism quite compromised.
5. there should not be anything beyond 4 since this is out of reach of server.
My implementation is in 4. This is the place I worried about as stated above. Sun maybe bypass my singleton obligation in adaptor and the testing program produce multiton data objects. Also, I am not sure right now: my locking is based on the cache but not as fine as at the record level. Will Sun be OK on my locking?
Points 1 -3 seem well described, however I don't see how point 4 follows from the earlier points. It would be quite possible for you to enforce a single copy of the cache / file access object within your Data class, allowing the Data class itself to be a multiton. This would allow greater concurrent access.
My implementation is in 4. This is the place I worried about as stated above. Sun maybe bypass my singleton obligation in adaptor and the testing program produce multiton data objects.
I am confused by this - if you have made your Data class a Singleton (no public constructor, class cannot be subclassed, ...) then Sun should not be able to bypass your design.
Thanks for your reply. In point 4 or my implementation, I made singleton at business logic (DBAdapter, which expose book and search functionality to client). in this level, it has internal static data object. So it is a layer beyond data access (data.class).
Sun could bypass it. Since if Sun want to check just the locking, it could create data object directly in its testing code; thus the DBAdapter is bypassed. This is what I detected the potential loophole in my design when I was testing my locking methods. In my testing, I directly call data object and its methods (I guess Sun would do the same that is one of the reasons they provided a unique DBAccess), meanwhile I run a client gui (which is thru the business logic layer) to see the effect. anything run by the testing after client gui is launched won't show up in jtable. Otherwise with my currect DBAdapter's exposed server functions, I don't see how automatic testing could be done unless Sun has its own business logic layer on top of our data access layer, which has its singleton data object (in Sun's business logic). However, at this point, I just don't know whether or not I can just take the Sun's provided assumption that at most one program is accessing the data file, because in my scenario described above there are 2 separate unrelated jvms and data objects.
I described the 4 possible layers where singleton can take place. These points don't work in the same layer. Point 3 works in the data access layer. Point 4 is the uppermost layer a singleton can take place in the server.
i not a java guru - far away from it, actually ;-)
but isn't a singleton widely regarded as bad OO design? are you sure you need one?
i'm using the following simple architecture:
Class "Data" implements interface "DBAccess", will be instantiated multiple times, one time per client. All "Data" instances share one static "DataFile", which handles all file operations, basically. The constructor of "Data" either creates a new "DataFile" instance or hooks on the existing one.
Perfectly fine in my opinion, but any comments strongly welcomed... ;-)
Andy - I understand your concern now. In point 4, you are not using the Singleton pattern, you are implementing at a business level the rule that there is only a single instance of the Data class.
In this case you should document that the user of your Data class should only instantiate a single instance. You should also document why you are not using a Singleton pattern, and when you believe multiple instances might be applicable. This documentation should probably be put in both the design decisions documentation, and in the JavaDoc documentation.
As long as you have it properly documented, then Sun should not take away marks if they go outside your clearly defined parameters.
Jan - "but isn't a singleton widely regarded as bad OO design?". Hmmm, that is a bit difficult to answer. The general problems with the Singleton pattern are not problems with the pattern itself - they are problems with implementation. The biggest problem is overuse (too many programmers fail to consider your question "are you sure you need one?"). The next biggest problem is incorrect implementation of the pattern (have you considered what happens if two threads try to do a lazy instantiation at the same time; have you considered subclasses of your Singleton, ...).
But all that said, there are places for the Singleton pattern, and when done properly, it can be a very useful tool.
Your brief overview of what you are doing sounds reasonable.
Thanks for your comments. I actually changed the implementation dates ago to do it in a category 3 (no, not record level locking). The change is just a couple of lines. But reflected from your comments, I do think and agree with you a singleton pattern is important and effective in our case.