My question is concerning whether or not I need to implement my Data class as a singleton.
In local mode, there will be only one client connected to one database, and therefore there will only be one instance of Data - no problems here.
In networked mode, there can be mulitple clients, but they all connect to one remote object on the server, which connects to only one instance of Data. My implementation relies on only one instance of Data existing at a time, which tells me that I should implement it as a singleton. But since my implementation never allows the possibility of more than one instance of Data at a time, do I need to make it a singleton? The only reason I can think of to do so is if my Data class would be considered for reuse in another application. But then again the specs say
The IT director does not anticipate much reuse of the first Java technology system...
B.S. University of Wisconsin<br />SCJP 1.4 (85%)<br />SCJD 1.4 (92%) B&S Contractors
I think if you ask people's opinion about singleton most of them will answer that there is nothing wrong with it, but your first choice should go to a non-singleton design. So in this case I can only say, figure out why exactly you want it to be singleton, and then try to find out if there are no other ways to accomplish the same result without singleton. If you cannot find a decent way, or they all interfere with some other design issue, then singleton is probably the way to go.
I did also use singleton, I will explain my situation and the logic which I used to validate the idea of implementing it as singleton. Maybe this will help you to find out if you need it or not.
Based upon your post I think that you nearly have the same design as I do. You have some kind of adapter for which you created a remote interface. The adapter has at most one instance to the Data class. So there will be multiple adapter instances when multiple clients are connected, but they will all share the same Data instance. My design (not all of it, just a snapshot) :
Note: The DatabaseAdapter instances are spawned by the RMI server when a new client connects. At least, this is what I think...
This design offers 2 layers of indepence.
1. You can choose any DB implementation to give to Database 2. You can choose to make any Database available for remote use
None of these classes contain business logic. They are all designed for re-use. One of these design reasons made me choose singleton for Data:
Each instance of the Data class is capable of using a different database file. Supose the company creates some other database file, using the same arhcitecture (the same header schema) but different fields & values, they can do this without changing the code. All they have to do is create the database file, create a javabean Object that represents a record from that Databasefile (get/sets), add a configuration line (which binds the java bean object with the actual data instance) somewhere and they are done.
Now, this involves multiple instances of Data, however, only ONE instance my manipulate the same database file. So, when I do
Data d1 =Data.getInstance("db1.db"); Data d2 =Data.getInstance("db2.db"); Data d3 =Data.getInstance("db1.db");
then: d1 == d3 && d1 != d2 && d2 != d3
1. putting 'synchronized' in the signature of the read/write methods is not an option since it are object locks and not class locks. Meaning that synchronized methods can be executed at the same time over different objects.
2. synchronizing on 'this' is the same as option 1
3. synchronizing on the class was an option, but that would mean that if other instances would exist which operate on a different database file, they would wait when another instance (that could be operating on another database file) is bussy with the read/write method. This is unacceptable.
4. synchronizing on the RAF was an option, but I had to make it static, and thus I could not offer the design advantage of letting Data instances access other database files
So, in my case I only had one option left and that is implementing it as a singleton per database file.
In your case (if you do not designed it to serve other files, which if certainly no must) I think option 3 and 4 are open. Personally, I think synchronizing on the RAF would be the best choice, but I could be wrong...
The DatabaseAdapter instances are spawned by the RMI server when a new client connects. At least, this is what I think...
Not true, at least in the default case. The RMI server will spawn a new *thread* to run on the *same* instance for each client. I have not worked out how to make RMI generate a new instance for each client.
Two reasons why you might want to use a factory pattern to enforce a shared instance of Data rather than a singleton: 1. Singletons implemented using static can cause problems in JUnittesting. 2. Can your singleton allow connections to fileA and fileB at the same time? Imagine if the system was expanded to provide hotels and flights via different databases, will your architecture extend?