3

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 animal

   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!

Sisyphus
  • 4,181
  • 1
  • 22
  • 15
Carven
  • 14,988
  • 29
  • 118
  • 161
  • Does a tree not contain the monkey, while the monkey also knows which tree he's in, and even perhaps how to count after his monkey fashion how many bananas are left in it? – Affe Jun 03 '11 at 06:57
  • @Affe, Thanks for adding a comment. I am still a little confused. Could you elaborate a little more? thanks! – Carven Jun 03 '11 at 07:14
  • That was my way of saying if your business/application domain includes two things that share a state, they are by definition coupled. What is the merit in jumping through hoops to try to model them otherwise? – Affe Jun 03 '11 at 07:19
  • yea, they are somewhat coupled but I was hoping that it will not be very tightly coupled that could have made the implementation to need to ensure all the referential integrity. Especially when there could be a bidirectional association. – Carven Jun 03 '11 at 08:13

4 Answers4

2
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'

WinW
  • 679
  • 2
  • 9
  • 20
  • That's a pretty good idea! But in the 2D array, the animals are planted all over the place. But when I need to know the location of a particular animal, I have to loop through the entire 2D array just to find its current location. Would this be too expensive to just find out its current location? More over, if the map gets bigger, the loop gets heavier too. – Carven Jun 03 '11 at 14:16
  • 2
    You could keep a dictionary of animal/location, which keeps the location of each animal... Then you'll have an O(1) access to its location. – Yochai Timmer Jun 04 '11 at 15:48
  • @xEnOn , Yes you are perfectly right, it would be expensive. that is why I suggested "Also, The animal's location property should be updated.". In realworld, if I occupy a space and if someone has to find where I am then he needs to search entire map-no other go. But we dont often like this- so we have techniques- like we say "I am in just behind you" , I am at home", etc. (I possess theknowledge). if I dont have the knowledge in a desert I say "I am Lost". Then it is tough for the finder to find me. So always good idea to attache location info to the Anima object :) – WinW Jun 06 '11 at 12:01
  • @xEnOn One possible modification is that animal/any object occupy space. So the array can be of type Interface:IOccupier, where Animal implements IOccupier, A car implements I Occupier. this way you can have extensibility. – WinW Jun 06 '11 at 12:23
1

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.

Op De Cirkel
  • 28,647
  • 6
  • 40
  • 53
0

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();

};

Chandan
  • 637
  • 1
  • 5
  • 13
  • This is a pretty good approach too! But just one thing, if I want to find out the position of a particular animal, I still have to loop through the entire map array to find out where it is at, right? Is this something that I cannot run away from no matter what kind of design I use? Of course, having a bidirectional relationship between the location and animal could avoid this loop but I don't know which is more worthwhile. – Carven Jun 04 '11 at 14:49
  • Yes you're right. This approach is ideal only if you need to search for Animal based on Location. But if its a 50x50 matrix, time overhead for looping through the whole matrix may be negligible. Also, you should consider how often does this request come. It all depends on what use case you're targeting. – Chandan Jun 06 '11 at 10:50
0

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.

Slobaloba
  • 11
  • 2