In such situations I have successfully introduced (reused) the "context" term with sometimes multiple layers.
This means a singleton, thus "global" object store, from which these kind of objects can be requested. Codes that require them, include the header of the store, and use the global functions to get their object instances (like now, the interest rate provider).
The store may be either:
- strictly typed: you include the headers for all the served types and so you can create typed accessors, like InterestRate getCurrentInterestRate();
- or generic: Object getObject(enum obType); and only extend the obType enum with the new kinds (obtypeCurrentInterestRate).
The bigger the system, the more usable the latter solution is, for a quite small risk of using the wrong enum. On the other hand, with languages that allow forward type declarations, I think you can use typed accessors without including all the headers in the store.
One more note: you may have multiple instances of the same object type for different uses, like sometimes different Language value for the GUI and for printout, global and session level logs, etc, so the enum / accessor name should NOT reflect the actual type, but the role of the requested instance (CurrentInterestRate).
In the store implementation, you have to manage the context levels and context instance collections. A simple example is web service, where you have the global context (one instance for all requests for that object - problematic when having a server farm), and a context for each web session. You can also have contexts for each user, who may have multiple, parallel sessions, etc. With multiple servers you should use a kind of distributed cache for such things.
When the request comes in, you decide which context level the requested object is, get that context for the call. If the object is there, you send it back; if not, you create and store it at that context level, and return it. Of course, synchronize the creation section (and publish it to the distributed cache). The creation can be configurable plugin-like, best with languages allowing creating object instances by their class name (Java, Objective C, ...), but you can do that in C as well with pluggable libraries having factory functions.
Side note: the caller should NOT know too much about its own contexts, and the requested object's context level. Reasons: 1: it is easy to make mistake (or "clever tricks") by playing with these parameters; 2: the context level of the requested might change later. I mostly connect context information to the thread, so the object store has the information without extra parameters from the request.
On the other hand, the request may contain hint for the instance: like getting interest rate for a specific date. It should be the same "global" access, but multiple instances depending on the date (and leading different date values to the same instance between rate changes), so it is advisable to add a "hint" object to the request, used by the instance factory and not the store; and a keyForHint to the factory, used by the store. You can add these functions later, I just mentioned.
For your case this is a kind of overkill (only one object is served in global level), but for a quite small and simple extra code right now, you get a mechanism for further, perhaps more complex requirements.
Another good news: if you are in Java, you get this service from Spring without thinking too much, I just wanted to explain it in details.
update
function that's called at each timestep? Can you post in pseudocode how your simulation operates? – James Jul 10 '12 at 2:19Singleton
is a global with OO syntactic sugar on it and is a terrible solution that tightly couples your code in some of the worst ways possible. Read this article over and over until you understand it! – user7519 Jul 10 '12 at 3:10DateTime
as input and return a number as output. – rwong Jul 10 '12 at 4:17