Object Relationship Design
I just happen to ponder of a OO concept which may sound quite trivial but I don't know why I find it quite confusing.
Anyway, I am thinking for example, if I have an Animal class and a Location class. And I only allow one animal to be at one location at any time. So it is kind of like a 1-to-1 relationship. At the same time, I wish that the Animal and Location classes do not need some kind of bidirectional reference so that they are kept loosely coupled. If say I have this:
class Animal {
private Location loc;
public Animal(int x, int y) {
loc = new Location(x,y);
}
public static newAnimal(Location[][] map, int x, int y) {
if(map[x][y] != null) {
return new Animal(x, y);
} else return null;
}
class Location extends Point {
public Location(int x, int y) {
super(x, y);
}
}
public static void main(String[] args) {
//populates a map
Location[][] map = new Location[10][10];
for(int x=0; x<10; x++) {
for(int y=0; y<10; y++) {
map[x][y] = new Location(x, y);
}
}
Animal dog = new Animal(2, 4); //dog is at location 2,4
Animal cat = new Animal(5, 6); //cat is at location 5,6
//But this does not restrict a constraint requirement that there should only be one animal at any one point
Animal horse = new Animal(2, 4); //now, horse is at the same location as dog but we only wanted one location to have one an开发者_开发技巧imal
Animal rabbit = Animal.newAnimal(map, 20, 50); //rabbit is null because it is out of the map size
}
From this, I foresee 2 problems.
First, because my location does not know if an animal is already on it, many animals can all be pointing to a same location on the map array. This would violate the 1-1 multiplicity constraint that I wanted. In my case, I let the Animal to own the Location. this could the be reason why this could happen. If say I let the Location to own the Animal, this could be solved. But in a case if I want to know where my Animal is at, I need to loop through the entire map just to find where one of my Animal's location is? Alternatively, I can keep a bidirectional reference but this would cause the classes to be highly-coupled.
The second problem that I feel could be a problem is the design in the Animal class. I have a static newAnimal() method to instantiate new animals. I did it this way because I thought allowing the caller to create new Animal instance directly from the constructor may allow an out of range coordinate input. But I still find the design very awkward.
I am using Java codes in my example. And I am thinking the design within the class objects itself and is not involving the database yet.
Any suggestions to improve the two issues I raised could be great. Thanks!
1.Location/Map in our case is a real world object and has boundaries.
2.Map can not hold more than one animal at any pont
3.An animal can not occupy more than one location
Above are the facts associated to the problem.
Location can be considered as a matrix. A 2-D array. For the time being we assume that one animal hold only a single unit (One cell) exactly and not any less or more than that at a given point of time.
This 2D array is of Animals (which can contain Animal objects only), then the containment is real, no two can occupy same space-it has to replace existing one to occupy.
Also, The animal's location property should be updated.
Alternatively, A LocationManagerClass can be written to store and manage Animals occupancy on map. But it is to be assed further if it is close to the real life scenaio of 'space occupancy'
I would have separate interface+class that manages/maintains the relation, and have methods to add new animal, or move animal to other location. In this way you can check and maintain your pre/post conditions easily. Also i would keep Animal and Location immutable (in this context). Having interface and class will make it easier to do different implementations of the relations: Map, DB, file, etc.
Why do you want the Animal class to contain Location?
An alternative would be to have only Animal properties in the Animal class. Location class is fine as it is. Have a third class called Map, that will manage the Locations(in the map) and the Animal present at each location.
A c++ code for this would be something like this:
class Animal
{
public:
Animal(char *name);
~Animal();
char *getName();
private:
char *name;
};
//Here I haven't used the Location class, instead I'm using x,y. You can make that small change.
class Map
{
private:
Animal *animalLocation[10][10];
public:
//Note this function will check if any Animal exists at the specified (x,y).
void addAnimal(int x, int y, void *animal);
void* getAnimal(int x, int y);
Map();
~Map();
};
You can use something like the previous answers but with another data structure instead of a 2D array. Such as a sparse array, ordered list or hash table. That will provide faster lookups but slower insertion or movement of animals. And it can still enforce the requirement of no more than 1 animal in any location.
精彩评论