Композиция является одним из методов проектирования, который реализовывает отношение типа has-a в классах. Мы можем использовать наследование в Java или композицию для повторного использования кода.
Композиция в Java достигается за счет использования переменных экземпляра, который ссылается на другие объекты.
Небольшой пример в теории: Person has a (имеет) Job.
А теперь практика на java:
Job.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package ua.com.prologistic.composition; public class Job { private String role; private long salary; private int id; public String getRole() { return role; } public void setRole(String role) { this.role = role; } public long getSalary() { return salary; } public void setSalary(long salary) { this.salary = salary; } public int getId() { return id; } public void setId(int id) { this.id = id; } } |
Person.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package ua.com.prologistic.composition; public class Person { //используем отношение has-a private Job job; public Person(){ this.job=new Job(); job.setSalary(1000L); } public long getSalary() { return job.getSalary(); } } |
А теперь протестируем: используем объект Person и получаем зарплату (salary)
TestPerson.java
1 2 3 4 5 6 7 8 |
public class TestPerson { public static void main(String[] args) { Person person = new Person(); long salary = person.getSalary(); } } |
Обратите внимание, что тестовая программа TestPerson не зависит от каких-либо изменений в объекте Job. Если вам нужно реализовать взаимодействие двух классов и вы хотите повторно использовать код, то лучшим выходом будет использование композиции вместо наследования.
Преимущества использования композиции в том, что мы можем управлять видимостью другого объекта для клиентских классов и повторно использовать только то, что нам нужно.
Кроме того, если есть какие-либо изменения в другой реализации класса, например, если метод getSalary()
начнет возвращать строку, то мы должны изменить класс Person, а не классы клиента.
Композиция в Java позволяет создавать back-end класс, когда это необходимо. Например, мы можем изменить getSalary()
метод класса Person для инициализации объекта Job.
Здравствуйте. Объясните пожалуйста следующий момент.
Вот определение Композиции которое представлено в Википедии:
Композиция — более строгий вариант агрегации. Известна также как агрегация по значению.
Композиция имеет жёсткую зависимость времени существования экземпляров класса контейнера и экземпляров содержащихся классов. Если контейнер будет уничтожен, то всё его содержимое будет также уничтожено.
В принципе это созвучно с тем, как излагают данный вопрос Джим Арлоу и Айла Нейштадт в книге UML2 :
Композиция — это строгая форма агрегации:
1) Одновременно части могут принадлежать только одному композиту — совместное владение частями невозможно.
2) композит обладает исключительной ответственностью за все свои части; это значит что он отвечает за их создание и уничтожение
3) композит может высвобождать части, передавая ответственность за них другому объекту
4) в случае уничтожения композита он должен уничтожить все свои части или передать ответственность за них другому объекту.
Вопрос в следующем: данный пример показывает свойства композиции или все таки агрегации, Ведь фактически пример не отвечает ни одному вышеперечисленному пункту. Или я что — то не так понимаю. Заранее благодарен.
Пример показывает как именно используется композиция , время жизни объекта job зависит от времени жизни экземпляра класса , а вот при агрегации нет , объект при агрегации может продолжать существовать после уничтожения экземпляра , дело в том, что при агрегации объект передается
как параметр.
Так при реассайне ссылки типа Job на объект, данный объект будет продолжать существование вне зависимости, что с Person дальше будет. Следовательно это агрегация.
А композиция была бы если определить внутренний нестатический класс Job и через this.new создать объект Job, который хранит ссылку на объект обрамляющего класса Person. И теперь, если что-то случиться с Person, Job также «потушится».