relationship among objects

Association

Association is a relationship between two objects. In other words, association defines the multiplicity between objects. You may be aware of one-to-one, one-to-many, many-to-one, many-to-many all these words define an association between objects. Aggregation is a special form of association. Composition is a special form of aggregation.
Example: A Student and a Faculty are having an association.

Aggregation

Aggregation is a special case of association. A directional association between objects. When an object ‘has-a’ another object, then you have got an aggregation between them. Direction between them specified which object contains the other object. Aggregation is also called a “Has-a” relationship.

Composition

Composition is a special case of aggregation. In a more specific manner, a restricted aggregation is called composition. When an object contains the other object, if the contained object cannot exist without the existence of container object, then it is called composition.
Example: A class contains students. A student cannot exist without a class. There exists composition between class and students.

=================================================================================

Association is a simple structural connection or channel between classes and is a relationship where all objects have their own lifecycle and there is no owner. 

Lets take an example of Department and Student. 

Multiple students can associate with a single Department and single student can associate with multiple Departments, but there is no ownership between the objects and both have their own lifecycle. Both can create and delete independently.

Here is respective Model and Code for the above example.

[​IMG]

The code


Code:
#include<iostream.h>

class Student;

class Department
{
    char* name_p;
  
  public:

    Department(char *dName)
    {
      cout<<"Department::ctor\n";
      name_p = new char(sizeof(strlen(dName)));
      name_p = dName;
    }

    char* dName() const
    {
      return(name_p);
    }

    ~Department()
    {
      cout<<"Department::dtor\n";
      delete(name_p);
    }

};

class Student
{
  char* name_p;

  public:

    Student(char *sName)
    {
      cout<<"Student::ctor\n";
      name_p = new char(sizeof(strlen(sName)));
      name_p = sName;
    }

    char* sName()const
    {
      return(name_p);
    }
    
    ~Student()
    {
      cout<<"Student::dtor\n";
      delete(name_p);
    };
};


class Course
{
    Student * std_p;
    Department * dept_p;
    char * courseName_p;

    static unsigned int index;
    static Course *courseList[4];

  public:
    
    Course(char* crseName, Student* student, Department* dept):
      courseName_p(0), std_p(student), dept_p(dept)
    {
      cout<<"Course:ctor\n";

      if (index < 4)
      {
        courseName_p = new char(sizeof(strlen(crseName)));
        courseName_p = crseName;
        
        //insert this Course in courseList
        courseList[index] = this;
        ++index;
      }
      else
      {
        cout<<"Cannot accomodate any more Course\n";
      }
    };

    ~Course()
    { 
      cout<<"Course:dtor\n";
      delete (courseName_p);
    };

    static char* findStudent(char *crseName, char* deptName)
    {
      for(int i=0; i<index; i++)
      {
        if ( (courseList[i]->getCourseName() == crseName) && 
             (courseList[i]->getDeptName() == deptName) )
        {
          return(courseList[i]->getStdName());
        }
      }
    }

    char * getStdName()const {return(std_p->sName());};
    char * getDeptName() const {return(dept_p->dName());};
    char * getCourseName()const {return(courseName_p);};
}; 

unsigned int Course::index =0;
Course* Course::courseList[4] = {0,0,0,0};


int main()
{
  int i;

  cout<<"\nExample of Association class...\n";
  cout<<"-----------------------------------\n\n";

  cout<<"We have got 4 students ...\n";
  Student *studentNames[4] = {new Student("Meera"), new Student("Moina"), new Student("Teena"), new Student("Mridula")} ;

  cout<<"\n";

  cout<<"We have got 2 Departments...\n";
  Department *departNames[2] = {new Department("Mathemetics"), new Department("ComputerSceince")} ;
  
  cout<<"\n";

  cout<<"Here class Course Associates Student and Department, with a Course name ...\n";
  Course course1("DataStructure",studentNames[0], departNames[1]);
  Course course2("Maths",studentNames[3], departNames[0]);
  Course course3("Geometry",studentNames[2], departNames[0]);
  Course course4("CA",studentNames[1], departNames[1]);

  cout<<"\n";

  cout<<"Finding a Student using Course and Department...\n";
  cout<<"Student who has taken Maths Course in Mathemetics Department is:"<<Course::findStudent("Maths", "Mathemetics")<<endl;
  
  cout<<"\n";

  cout<<"Deletion of objects...\n\n";

  for(i=0; i<4; ++i)
  {
    delete studentNames[i];
  }

  cout<<"\n";

  for(i=0; i<2; ++i)
  {
    delete departNames[i];
  }

  cout<<"\n";

  return(0);
}

output:
------

Example of Association class...
-----------------------------------

We have got 4 students ...
Student::ctor
Student::ctor
Student::ctor
Student::ctor

We have got 2 Departments...
Department::ctor
Department::ctor

Here class Course Associates Student and Department, with a Course name ...
Course:ctor
Course:ctor
Course:ctor
Course:ctor

Finding a Student using Course and Department...
Student who has taken Maths Course in Mathemetics Department is:Mridula

Deletion of objects...

Student::dtor
Student::dtor
Student::dtor
Student::dtor

Department::dtor
Department::dtor

Course:dtor
Course:dtor
Course:dtor
Course:dtor
Aggregation is a specialize form of Association where all object have their own lifecycle but there is a ownership like parent and child. Child object can not belong to another parent object at the same time. We can think of it as "has-a" relationship.

Implementation details:
  1. Typically we use pointer variables that point to an object that lives outside the scope of the aggregate class
  2. Can use reference values that point to an object that lives outside the scope of the aggregate class
  3. Not responsible for creating/destroying subclasses
Lets take an example of Employee and Company. 

A single Employee can not belong to multiple Companies (legally!! ), but if we delete the Company, Employee object will not destroy. 

Here is respective Model and Code for the above example.

[​IMG]

The code


Code:
#include<iostream.h>

class Employee
{
  public:

    Employee(char *name){
      cout<<"Employee::ctor\n";
      myName_p = new char(sizeof(strlen(name)));
      myName_p = name;
    }
    
    char* disp(){return(myName_p);};

    ~Employee()
    {
      cout<<"Employee:dtor\n\n";
      delete (myName_p);
    }

  private:
    char *myName_p;
};

class Company
{
  public:
    Company(char * compName, Employee* emp){
      cout<<"Company::ctor\n";
      name = new char(sizeof(strlen(compName))); 
      name = compName;
      myEmp_p = emp;
    };

    ~Company()
    {
      cout<<"Company:dtor\n\n";
      myEmp_p = NULL;
    };
    
  private:
    char *name;
    Employee *myEmp_p;
};


int main()
{
  cout<<"\nExample of Aggregation Relationship \n";
  cout<<"-----------------------------------------\n\n";
    
  {
    cout<<"Here, an Employee-Keerti works for Company-MS \n";
    Employee emp("Keerti");
  
    {
      Company comp("MS", &emp);
    } // here Company object will be deleted, whereas Employee object is still there

    cout<<"At this point Company gets deleted...\n";
    cout<<"\nBut Employee-"<<emp.disp();
    cout<<" is still there\n";
    
  } //here Employee object will be deleted

  return(0);
}

output:
-------

Example of Aggregation Relationship 
-----------------------------------------

Here, an Employee-Keerti works for Company-MS 
Employee::ctor
Company::ctor
Company:dtor

At this point Company gets deleted...

But Employee-Keerti is still there
Employee:dtor

Composition is again specialize form ofAggregation. It is a strong type of Aggregation. Here the Parent and Child objects have coincident lifetimes. Child object dose not have it's own lifecycle and if parent object gets deleted, then all of it's child objects will also be deleted. 

Implentation details:

1. Typically we use normal member variables
2. Can use pointer values if the composition class automatically handles 
allocation/deallocation
3. Responsible for creation/destruction of subclasses 

Lets take an example of a relationship between House and it's Rooms. 

House can contain multiple rooms there is no independent life for room and any room can not belong to two different house. If we delete the house room will also be automatically deleted. 

Here is respective Model and Code for the above example.

[​IMG]

The code


Code:
#include<iostream.h>

class House;

class Room
{
  public:

    Room()
    {
    };

    static void createRoom_v(Room* (&room), House* hse, char* name)
    {
      room = new Room(hse, name); 
    }
    
    Room(House* hse, char* myName)
    {
      cout<<"Room::ctor\n";
      myHse_p = hse;
      
      if(NULL != myHse_p)
      {
        name_p = new char(sizeof(strlen(myName)));
        name_p = myName;
      }
      else
      {
        cout<<"Oops House itself is not Created Yet ...\n";
      }
    };

    ~Room()
    {
      cout<<"Room:dtor\n";
      myHse_p = NULL;
      delete (name_p);
    };

    void disp()
    {
      cout<< name_p;
      cout<<"\n";
    }
    
    static void initList_v(Room *(& roomsList_p)[3])
    {
      roomsList_p[3] = new Room[3];
    }

  private:
    House * myHse_p;
    char * name_p;
};

class House
{
  public:

    House(char *myName)
    {
      cout<<"House::ctor\n";
      name_p = new char(sizeof(strlen(myName)));;
      name_p = myName;

      Room::initList_v(roomsList_p);

      Room* myRoom;
      Room::createRoom_v(myRoom, this, "Kitchen");
      roomsList_p[0] = myRoom;
      
      Room::createRoom_v(myRoom, this, "BedRoom");
      roomsList_p[1] = myRoom;

      Room::createRoom_v(myRoom, this, "Drwaing Room");
      roomsList_p[2] = myRoom;
    }
    
    ~House()
    {
      cout<<"House:dtor\n";
      unsigned int i;
      
      cout<<"Delete all the Rooms ...\n";
      for(i=0; i<3; ++i)
      {
        if(roomsList_p[i] != NULL)
        {
          delete (roomsList_p[i]);
        }
          
      }
      delete [] roomsList_p;
      delete (name_p);
    }

    void disp()
    {
      cout<<"\n\nName of the House :"<<name_p;
      
      if(roomsList_p != NULL)
      {
        unsigned int i;
        cout<<"\n\nRooms details...\n";
        for(i=0; i<3; ++i)
        {
          if(NULL != roomsList_p[i])
          {
            roomsList_p[i]->disp();
          }
        }
        cout<<"\n\n";
      }
    }

  private:
    char* name_p;
    Room* roomsList_p[3];
};

int main()
{
  
  cout<<"\nExample of Composition Relationship\n";
  cout<<"-----------------------------------------\n\n";
  House hse("Vishranti Nilaya");

  cout<<"\n\nHouse details...\n";
  hse.disp();

  cout<<"Here House itself creates the Rooms and Deletes as well, before it gets deletd...\n";

  return(0);
}

output:
-------
Example of Composition Relationship
-----------------------------------------

House::ctor
Room::ctor
Room::ctor
Room::ctor


House details...


Name of the House :Vishranti Nilaya

Rooms details...
Kitchen
BedRoom
Drwaing Room


Here House itself creates the Rooms and Deletes as well, before it gets deletd...
House:dtor
Delete all the Rooms ...
Room:dtor
Room:dtor
Room:dtor
These relationships can also be explained with simple examples as below 
(these lines I have read in some blog):

Association:
  1. Create a folder called "Links"
  2. Create a shortcut/link inside this folder and link it to www.go4expert.com
  3. Create another shortcut/link instide this folder and link it to www.google.com
  4. Ask your friend to do the same on another machine using same links (www.go4expert.com and www.google.com)
  5. Delete the "Links" folder, and open your browser to check if www.go4expert.com and www.google.com still exist or not ;)
Briefly, Association is a relationship where all the objects have different lifecycles. there is no owner.

Aggregation:
  1. Create a file called file.txt
  2. Make a simple Application to open the File.txt (rw mode), but don't program it close the connection.
  3. Run an instance of this application (it should work ok and can open the file for rw)
  4. Keep the first instance, and run another instance of this application (In theory it should complain that it can't open the file in rw mode because it is already used by other application).
  5. Close the 2 instances (make sure you close the connection).
From the above application, we understand that the Application and the File has a separate lifecycles, however this file can be opened only by one application simuletanously (there is only one parent at the same time, however, this parent can move the child to another parent or can make it orphan).

Composition:
  1. Open a new Document name it as test.txt
  2. Write this sentence inside this document "This is a composition".
  3. Save the document.
  4. Now, delete this document.



This is what is called composition, you can't move the sentence "This is a omposition" from the document because its lifecycle is linked to the parent (i.e. the document here !!)

No comments:

Post a Comment