📜 ⬆️ ⬇️

Class Relationships - From UML To Code

Introduction

The UML class diagram allows you to designate relationships between classes and their instances. What are they needed for? They are needed, for example, to model an application area. But how are relationships reflected in the program code? This small study attempts to answer this question — to show this relationship in code.

First, let's try to clarify how the relationships between classes in the UML relate to each other. Using various sources, it was possible to construct the following structural diagram demonstrating the types of relationships:


Fig. 1 - Relations between classes

Associations have navigation: bidirectional or unidirectional, indicating the direction of communication. That is, each type of association still has two subspecies, which are not shown in the figure.
')
1. Summary

So, our goal is to build a UML class diagram (Class Model), and then reflect it in object-oriented code.

As an application area, take the human resources department of a certain enterprise and begin to build its model. For examples we will use the Java language.

The generalization relationship is inheritance. This attitude is well considered in every textbook of any OOP language. In Java, it has an explicit implementation through extending one class to another.


Fig. 2 - Generalization relation

The “Man” class (man) is more abstract, and the “Employee” (employee) is more specialized. The “Employee” class inherits the “Man” properties and methods.

Let's try to write the code for this diagram:
public class Man{ protected String name; protected String surname; public void setName(String newName){ name = newName; } public String getName(){ return name; } public void setSurname(String newSurname){ name = newSurname; } public String getSurname(){ return surname; } } //   Man public class Employee extends Man{ private String position; //    public Employee(String n, String s, String p){ name = n; surname = s; position = p; } public void setPosition(String newProfession){ position = newProfession; } public String getPosition(){ return position; } } 


2. Association

The association shows the relationships between the class instance objects.
2.1 Binary

The class “IdCard” was added to the model, which represents the employee identification card (pass). Only one ID card can correspond to each employee, communication power is 1 to 1.

Fig. 3 - Binary Association

Classes:
 public class Employee extends Man{ private String position; private IdCard iCard; public Employee(String n, String s, String p){ name = n; surname = s; position = p; } public void setPosition(String newPosition){ position = newPosition; } public String getPosition(){ return position; } public void setIdCard(IdCard c){ iCard = c; } public IdCard getIdCard(){ return iCard; } } public class IdCard{ private Date dateExpire; private int number; public IdCard(int n){ number = n; } public void setNumber(int newNumber){ number = newNumber; } public int getNumber(){ return number; } public void setDateExpire(Date newDateExpire){ dateExpire = newDateExpire; } public Date getDateExpire(){ return dateExpire; } } 


In the body of the program we create objects and link them:
 IdCard card = new IdCard(123); card.setDateExpire(new SimpleDateFormat("yyyy-MM-dd").parse("2015-12-31")); sysEngineer.setIdCard(card); System.out.println(sysEngineer.getName() +"    "+ sysEngineer.getPosition()); System.out.println("   " + new SimpleDateFormat("yyyy-MM-dd").format(sysEngineer.getIdCard().getDateExpire()) ); 


The Employee class has a card field whose IdCard type, as well as a class has methods for assigning a value (setIdCard) to this field and for
get value (getIdCard). From an instance of an Employee object, we can find out about an IdCard object associated with it, which means
navigation (arrow on line) is directed from Employee to IdCard.

2.2 N-ary association

Imagine that the organization should be assigned to employees of the premises. Add a new class Room.
Each employee object (Employee) can correspond to several workrooms. Communication power is one-to-many.
Navigation from Employee to Room.

Fig. 4 - N-ary association

Now we will try to reflect this in the code. New class Room:
 public class Room{ private int number; public Room(int n){ number = n; } public void setNumber(int newNumber){ number = newNumber; } public int getNumber(){ return number; } } 


Add a field and methods to work with Room to the Employee class:
 ... private Set room = new HashSet(); ... public void setRoom(Room newRoom){ room.add(newRoom); } public Set getRoom(){ return room; } public void deleteRoom(Room r){ room.remove(r); } ... 


Example of use:
 public static void main(String[] args){ Employee sysEngineer = new Employee("John", "Connor", "Manager"); IdCard card = new IdCard(123); card.setDateExpire(new SimpleDateFormat("yyyy-MM-dd").parse("2015-12-31")); sysEngineer.setIdCard(card); Room room101 = new Room(101); Room room321 = new Room(321); sysEngineer.setRoom(room101); sysEngineer.setRoom(room321); System.out.println(sysEngineer.getName() +"    "+ sysEngineer.getPosition()); System.out.println("   " + sysEngineer.getIdCard().getDateExpire()); System.out.println("   :"); Iterator iter = sysEngineer.getRoom().iterator(); while(iter.hasNext()){ System.out.println( ((Room) iter.next()).getNumber()); } } 

2.3 Aggregation

Let's introduce the Department class into our model - our enterprise is structured by departments. In each department can work one or more people. We can say that the department includes one or more employees and thus aggregates them. An enterprise may have employees who do not belong to any department, for example, an enterprise director.

Fig. 5 - Aggregation

Department class:
 public class Department{ private String name; private Set employees = new HashSet(); public Department(String n){ name = n; } public void setName(String newName){ name = newName; } public String getName(){ return name; } public void addEmployee(Employee newEmployee){ employees.add(newEmployee); //      newEmployee.setDepartment(this); } public Set getEmployees(){ return employees; } public void removeEmployee(Employee e){ employees.remove(e); } } 


So, our class, in addition to the constructor and the method of changing the name of a department, has methods for adding a new employee to the department, for deleting an employee and for getting all the employees in this department. Navigation in the diagram is not shown, which means it is bidirectional: from an object of type “Department” you can find out about an employee and from an object of type “Employee” you can find out which department it belongs to.

Since we need to easily recognize which department an employee belongs to, we will add a field and methods to the Employee class to assign and receive a department.

 ... private Department department; ... public void setDepartment(Department d){ department = d; } public Department getDepartment(){ return department; } 


Using:

 Department programmersDepartment = new Department(""); programmersDepartment.addEmployee(sysEngineer); System.out.println("   "+sysEngineer.getDepartment().getName()); 

2.3.1 Composition

Suppose that one of the requirements for our system is the requirement to store information about the previous position in the enterprise.
We introduce a new class “pastPosition”. In addition to the “name” property, we also introduce the “department” property, which will connect it with the “Department” class.

The data on past positions are part of employee data, thus the whole-part relationship between them and at the same time, data on past positions cannot exist without an object of the “Employee” type. Destroying an Employee object should result in the destruction of pastPosition objects.

Fig. 6 - Composition

Class "PastPosition":
 private class PastPosition{ private String name; private Department department; public PastPosition(String position, Department dep){ name = position; department = dep; } public void setName(String newName){ name = newName; } public String getName(){ return name; } public void setDepartment(Department d){ department = d; } public Department getDepartment(){ return department; } } 

In the Employee class, add properties and methods for working with data about a previous position:
 ... private Set pastPosition = new HashSet(); ... public void setPastPosition(PastPosition p){ pastPosition.add(p); } public Set getPastPosition(){ return pastPosition; } public void deletePastPosition(PastPosition p){ pastPosition.remove(p); } ... 


Application:
 //   sysEngineer.setPosition(""); //    : System.out.println("   :"); Iterator iter = sysEngineer.getPastPosition().iterator(); while(iter.hasNext()){ System.out.println( ((PastPosition) iter.next()).getName()); } 


3. Dependency

To organize a dialogue with the user, we will introduce the class “Menu” into the system. We build one “showEmployees” method that shows the list of employees and their positions. The parameter for the method is an array of "Employee" objects. Thus, changes made to the Employee class may require changes to the Menu class.

Fig. 7 - Dependency

Note that the class “Menu” does not belong to the application area, but is a “system” class of an imaginary application.
Class "Menu":
 public class Menu{ private static int i=0; public static void showEmployees(Employee[] employees){ System.out.println(" :"); for (i=0; i<employees.length; i++){ if(employees[i] instanceof Employee){ System.out.println(employees[i].getName() +" - " + employees[i].getPosition()); } } } } 


Using:
 //     Employee director = new Employee("", "", ""); Menu menu = new Menu(); Employee employees[] = new Employee[10]; employees[0]= sysEngineer; employees[1] = director; Menu.showEmployees(employees); 

4. Implementation

An implementation, like inheritance, has an explicit expression in the Java language: an interface declaration and the possibility of its implementation by some class.

To demonstrate the “implementation” relationship, create the “Unit” interface. If we imagine that an organization can be divided not only into departments, but, for example, into workshops, branches, etc. The “Unit” interface is the most abstract unit of division. In each unit of division, a certain number of employees work, therefore the method for obtaining the number of working people will be relevant for each class implementing the “Unit” interface.


Fig. 8 - Implementation

Interface "Unit":

 public interface Unit{ int getPersonCount(); } 

Implementation in the class "Department":
 public class Department implements Unit{ ... public int getPersonCount(){ return getEmployees().size(); } 


Application:
 System.out.println("  "+sysEngineer.getDepartment().getName()+"  " +sysEngineer.getDepartment().getPersonCount()+" ."); 


As you can see, the implementation of the getPersonCount method is not quite relevant for the Department class, since it has the getEmployees method, which returns
collection of objects "Employee".

Complete code: http://code.google.com/p/umljava/downloads/list

findings

The UML modeling language has a set of relationships for building a class model, but even a developed OOP language like Java has only two explicit constructs to reflect relationships: extends (extension) and interface / implements (implementation).
As a result of the simulation, we obtained the following diagram:


Fig. 8 - class diagram

Literature

1) G. Butch, D. Rambo, A. Jacobson. UML Language User Guide.

2) A.V. Leonenkov. UML Tutorial

3) Ekkel B. Philosophy of Java. Library programmer. - SPb: Peter, 2001. - 880 p.

4) S. Orlov. Software Development Technologies: Tutorial. - SPb: Peter, 2002. - 464 p.

5) Mukhortov VV, Rylov V.Yu. Object-oriented programming, analysis and design. Toolkit. - Novosibirsk, 2002.

6) Anand Ganesan. Modeling Class Relationships in UML

Source: https://habr.com/ru/post/150041/


All Articles