В предыдущей статье мы узнали о том, как JAVA реализует концепцию наследования для создания иерархий классов https://medium.com/@konlanmikpekoah.km/understanding-inheritance-using-java-bbe184bc824b.
В этом примере мы увидим, как мы можем использовать концепцию, называемую композицией, для создания сложных объектов из более простых. Итак, вы, возможно, помните, что модель наследования — это тип отношений.
Итак, здесь, на этой диаграмме классов, объект книги является публикацией, поскольку он наследуется от базового класса публикации, а также получает все атрибуты и методы из базового класса. Таким образом, мы также можем сказать, что журнал — это периодическое издание, и мы можем видеть, что журнал — это публикация, потому что, опять же, он имеет тот же общий базовый класс.
Состав работает немного по-другому. При использовании композиции мы строим объекты из других объектов, и эта модель больше похожа на взаимосвязь.
Итак, на приведенной выше диаграмме объект книги имеет объект автора, который содержит информацию об авторе. Вместо того, чтобы определять всю информацию, связанную с автором, непосредственно в иерархии классов книги. Этот тип модели позволяет нам извлекать отдельные идеи и помещать их в свои собственные классы. Теперь наследование и композиция не исключают друг друга, вы можете комбинировать их в зависимости от потребностей вашего приложения. Итак, давайте применим эту концепцию к реальному коду, чтобы увидеть, как это работает.
Book.java
import java.util.ArrayList; import java.util.List; public class Book { private String title; private double price; private String authorFname; private String authorLname; List<String> chapters = new ArrayList(); public Book(String title, double price, String authorFname, String authorLname) { this.title = title; this.price = price; this.authorFname = authorFname; this.authorLname = authorLname; } public void addChapter(String chapterName){ chapters.add(chapterName); } }
И я определил класс книги, есть название и цена, а также некоторая информация об авторе, имя и фамилия, и есть атрибут для хранения списка информации о главах. Также есть метод добавления глав в книгу, и он берет название главы и добавляет его в список массивов. Это конкретное определение класса прекрасно и хорошо, но оно довольно монолитно.
Есть фрагменты информации, такие как автор и, возможно, информация о главах, которые имеет смысл рассматривать как отдельные сущности. Нетрудно представить себе сценарий, в котором мы могли бы захотеть работать только с группой авторов или получить информацию о конкретных главах книги. Таким образом, мы можем использовать композицию, чтобы отделить эти отдельные фрагменты информации от общего объекта книги. Итак, давайте начнем с извлечения информации об авторе в отдельный класс.
Автор.java
public class Author { private String firstName; private String lastName; public Author(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } }
Итак, мне нужно изменить класс книги, чтобы использовать объект автора в качестве аргумента в конструкторе.
Book.java
import java.util.ArrayList; import java.util.List; public class Book { private String title; private double price; private Author author; List<String> chapters = new ArrayList(); public Book(String title, double price, Author author) { this.title = title; this.price = price; this.author = author; } public void addChapter(String chapterName){ chapters.add(chapterName); } }
Итак, теперь мы создали отношения, в которых с книгой связан автор, вместо того, чтобы хранить детали реализации данных об авторе внутри класса книги.
Итак, давайте продолжим и создадим отдельный класс для глав.
мы даже добавили pageCount для каждой главы в классе глав.
public class Chapter { private String name; private int pageCount; public Chapter(String name, int pageCount) { this.name = name; this.pageCount = pageCount; } }
теперь мы создали отношение, в котором книга имеет набор объектов глав. Мы даже можем добавить новый метод, и мы назовем его получить количество страниц книги, с помощью которого книга может вычислить свое собственное количество страниц.
import java.util.ArrayList; import java.util.List; public class Book { private String title; private double price; private Author author; List<Chapter> chapters = new ArrayList(); public Book(String title, double price, Author author) { this.title = title; this.price = price; this.author = author; } public void addChapter(Chapter chapter){ chapters.add(chapter); } public int totalPageNumber(){ int result = 0; for( Chapter chapter: chapters){ result += chapter.getPageCount(); } return result; } }
Итак, теперь у нас есть хорошее разделение обязанностей. Так, например, печать полного имени автора выполняется в классе author. Так что мы можем распечатать автора книги, а название оставим в покое. И вычисление размера книги выполняется с использованием данных, которые находятся в классе глав. У нас есть извлеченные объекты главы и автора, и мы обновили класс книги, чтобы вместо этого использовать эти данные.
в заключение
Итак, мы взяли монолитное определение класса и сделали его более расширяемым и гибким, составив его из более простых объектов класса, каждый из которых отвечает за свои функции и данные.