Introduction
The relationship between objects defines how these objects will interact or collaborate to perform an operation in an application. In any application, objects of user interface classes interact with the business layer objects in order to perform an operation. And in the background, the business layer objects may interact with objects of some repository which in turn talks to some data source object or service object.
Case Study
Before we go ahead, let's consider a Customer Order Management application that manages the orders placed by its customers for some products. Each order can have one or more products. The first is to sort out the independent classes from the given description. The following classes can be derived by using single responsibility principle.
- Customer: represents a customer who can place an order for any product
- Address: represents the address of a customer or the shipping address of an order
- Order: represents an order placed by a customer
- OrderItem: represents a product for which the order was placed by the customer
- Product: represents the product itself
- CustomerRepository: this class has the responsibility to serialize (save) and deserialize (retrieve) the customer to and from the data source
- OrderRepository: this class has the responsibility to serialize (save) and deserialize (retrieve) the order to and from the data source
- ProductRepository: this class has the responsibility to serialize (save) and deserialize (retrieve) the product to and from the data source
Types of Object Relationships
The basic types of relationships in object-oriented programming are.
- Collaboration
- Aggregation
- Inheritance
Let's explore them in more detail.
Collaboration
The collaboration relationship is sometimes referred as "uses a" relationship. Two objects are said to be collaborating when one object makes use of another unrelated object to complete an operation.
In our application, in order to save and retrieve the customer details, the CustomerRepository uses a Customer object to serialize (save) and deserialize (retrieve) the data to and from the data source. Similarly, other repository classes like ProductRepository and OrderRepository uses Product and Order objects respectively and therefore are said to be collaborating to perform an operation.
public class Customer
{
public Customer() : this(0)
{ }
public Customer(int customerId)
{
this.CustomerId = customerId;
AddressList = new List<Address>();
}
public int CustomerId { get; private set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public List<Address> AddressList { get; set; }
public bool Validate()
{
bool isValid = true;
if (string.IsNullOrWhiteSpace(FullName) ||
string.IsNullOrWhiteSpace(EmailAddress))
isValid = false;
return isValid;
}
}
public class CustomerRepository
{
// Retrieves a single customer
public Customer Retrieve(int customerId)
{
// Create an instance of the Customer Class
Customer customer = new Customer(customerId);
// Code that retrieves the defined Customer
// Populate the customer object and return
return customer;
}
// Retrieves all customers
public IEnumerable<Customer> Retrieve()
{
// Code that retrieves all customers
return new List<Customer>();
}
// Saves the current customer
public bool Save(Customer customer)
{
// Code that saves the defined customer
return true;
}
}
In our CustomerRepository class, you must have noticed that the CustomerRepository retrieves the customer details from the data source; populates the Customer object created in the process and returns the same. It also uses a Customer object while saving the customer details back into the data source.
Aggregation
The composition relationship is sometimes referred as “has a” relationship. In this type of relationship, an object can be composed of one or more objects in the form of its properties. Below are some facts that can be drawn from the given application description.
- Every Customer has an Address at which the ordered product will be shipped
- Every Order has - a customer, a shipping address, and a product represented as an OrderItem
It can be easily derived from the above facts that our Order class object is composed of Customer, Address, and OrderItem objects. The OrderItem object is further composed of the Product class object. The Order class composes these objects as its properties, as shown in the code below.
public class Order
{
// an object can compose other objects as its Properties
public Customer Customer { get; set; }
public Address ShippingAddress { get; set; }
public List<OrderItem> OrderItems { get; set; }
}
Composition
Composition is a special type of aggregation relationship whereby, the component parts do not exist except as a part of the composition.
In our application, for example, the object of the Order class is composed of a Customer and an OrderItem. If we break the relationship between the Order and Customer classes, the Customer class can still exit. But if the relationship between the Order class and OrderItem class is broken, then the OrderItem class cannot exist.
Assume that the functionality of our application changes in the future and instead of taking product orders, now it provides some other services to the existing customers, say a messaging service. In this scenario, the Order class will be of no use now. However, the Customer class which was once composed by the Order class can still exist without it. On the contrary, the OrderItem class cannot.
The type of relationship shared between Order and OrderItem classes is known as the Composition relationship.
Inheritance
Inheritance is a big topic in itself to talk about. Here, we are not talking about the different types of inheritance and how it is implemented in code. We will only be talking about inheritance as a relationship.
Inheritance is sometimes referred to as "is a" relationship. In this type of relationship, one class inherits the members of another class. The inherited class is known as the base class, whereas the inheriting class is known as the derived class. As the derived class has the members of base class, it can be said that the derived class is a sub-type of the base class. The derived class may or may not have members other than the inherited ones.
Assume that our application is running quite well in the market. Seeing that, the product owner now wants to add a new feature in the application that would monitor the type of products having a high demand. From the new requirement, it is quite clear that we will have to create sub-types of our Product class. These sub-types will represent the specialized product categories in the real world, as shown in the image below.
The classes MusicAlbum and Book, as shown in the above image have some properties of their own. And because they inherit from the Product class, they inherit its properties as well. So it can be said that MusicAlbum is a type of Product and so is the Book.
I hope this helps you get a basic understanding of the object relationships. It’s always great to have feedback from the readers. Your valuable feedback, questions, or comments about this article are always welcome.