Re: Design question: Multiplying singletons
- From: kelvSYC <kelvSYC@xxxxxxxxxxxxxxxx>
- Date: Thu, 26 Apr 2007 20:40:25 GMT
In article <Gb5Yh.5152$Zm.5122@trndny03>, H. S. Lahman
<h.lahman@xxxxxxxxxxx> wrote:
Responding to KelvSYC...
1 R1 *
[A] ------------- [B]
| 1
|
| R2
|
| *
[C]
where the requirements dictate that only one A may exist no matter how
many [B] or [C] objects there are (i.e., R1 and R2 always have the same
A on the 1-side for every B and C). So one implements [A] as a Singleton
pattern.
All that A::getInstance() is doing is providing reference for [B] or [C]
objects to use to instantiate their R1 or R2 relationship. Then
A::getB() and A::getC() just provides navigation through A when a B
needs to collaborate with a C or vice versa.
The problem is that if there are multiple [B] or [C] objects, one can't
provide that navigation with your implementation of A::getB() and
A::getC(). That is because the single A instance is actually related to
multiple Bs and Cs. So long as the [B] or [C] side is *, then one needs
a collection to manage the 1:* relationship and the accessors need to
know which particular B or C one is after within the collection:
A::getB(bID) and A::getC(cID). So...
This is a valid concern in one-to-many relationships - I'd have to take
note of that.
But suppose the relationships were one-to-one - that is, you could fold
everything in B (or C) back to A, but then A would simply balloon in
size or manageability (B or C may or may not be singleton, which would
be moot). Going back to the original question, with the one-to-one
relationship in mind, how would you keep track of the A associated with
a B (or C) if A was no longer singleton? Would the controller idea
work?
Ok, let's take a look at it:
1 R1 1
[A] ------------- [B]
| 1
|
| R2
|
| 1
[C]
If the relationships are 1:1 as above, then a given A can only be
related to exactly one B and one C at a time. Since A is a Singleton,
there can only be one instance of A. So exactly one B and one C is
accessible from that single instance of A.
Similarly, a B can be related to only one A and a C can be related to
only one A. Since there is only one A, then the model says that there
can only be on B and one C as well.
That changes as soon as A is not restricted to be a Singleton. Now if
there are N As, there can be N Bs and N Cs. Each A instance can be
related to a different B and C instance. As it happens, since the
relationship is unconditional on both ends, there must be exactly N Bs
and exactly N Cs and each A must be connected to different Bs and Cs.
[If, say, two As were related to the same B, then that B would be
related to two As, violating the A-side 1 multiplicity. If there were
more Bs than As, then some Bs would be unrelated to an A. If there were
less Bs than As, then some As would be unconnected to a B.]
Thus a 1:1 relationship is a very, very strong constraint on the
structure of set connectivity. (A tad pedantic, but I wanted to make
sure we were on the same page.)
So to answer your question, one would usually instantiate each
relationship with a pointer in each class (two in A). To ensure
referential integrity, that pointer would need to be instantiated before
any participant was accessed. That effectively means that one must
create an A, a B, and a C at the same time and assign the four pointers
at that time. ("At the same time" typically means within a single method
scope; otherwise one has to provide other infrastructure to ensure
access will not be premature.)
Typically one would do that with some sort of "factory" object that
created the triplet. That factory object would map to your controller.
But its responsibilities would be limited to instantiation and its
heavy-duty responsibility would be understanding that A, B, anc C needed
to be created as a triplet so that referential integrity could be
enforced by instantiating their relationships.
I would have envisioned that A, B, and C would need to be instantiated
all at once, thus a factory would be needed - but in this case is
two-way referencing necessary (ie. is the pointer in B to A necessary)?
If A, B, C represented some kind of part-whole hierarchy (A being the
whole, B and C being parts), then it seems kind of ugly to have an A
reference in B (as it would make sence to keep references to the parts
in the whole, but not as much to keep the reference to the whole in the
parts).
Suppose we have this:
class AController {
// assume it is singleton
private Array<A> as;
private AssociativeArray<B,A> bMap;
public void instantiateA() {
// instantiate B and C
// instantiate A
// add A instance to as
// add the B instance and A instance to bMap
}
// also some other method that removes stuff from bMap whenever A
gets deallocated, I presume
}
Would this be a good substitute for keeping an A reference in B? Does
it introduce some chicken-and-egg problem that I may have to address?
Collections are a fairly easy extension; one just replaces the pointer
with a collection handle. However, referential integrity now involves
making sure the collection has the /right/ instances at the time of
collaboration. (Once there is one instance available, multiplicity and
conditionality are no help in determining which particular ones must be
around at a given moment in time.)
What's the difference between a one-to-many relationship between A and
B and a one-to-one relationship between A and a collection of Bs?
--
I am only a mirage.
.
- Follow-Ups:
- Re: Design question: Multiplying singletons
- From: H. S. Lahman
- Re: Design question: Multiplying singletons
- References:
- Design question: Multiplying singletons
- From: kelvSYC
- Re: Design question: Multiplying singletons
- From: H. S. Lahman
- Re: Design question: Multiplying singletons
- From: kelvSYC
- Re: Design question: Multiplying singletons
- From: H. S. Lahman
- Design question: Multiplying singletons
- Prev by Date: Re: Design question: Multiplying singletons
- Next by Date: Re: Modeling events that occur in a game world
- Previous by thread: Re: Design question: Multiplying singletons
- Next by thread: Re: Design question: Multiplying singletons
- Index(es):
Relevant Pages
|