Composition
Objective
- Composition and its practical applications in software development.
- Build a complete example using object-oriented programming with composition.
Exercise 1*
Customer Class
A class can have references to objects of other classes as members. This is called composition and is sometimes referred to as a has-a relationship. For example, a Customer object needs to record the Address of the client. The address is not a simple string, it is another object with many fields.
-
Add the following
CustomerandAddressclasses to your project:Customer.javapublic class Customer { private String name; private String phone; private int id; public Customer(String name, String phone, int id) { this.name = name; this.phone = phone; this.id = id; } public String getName() { return name; } public String getPhone() { return phone; } public int getId() { return id; } public void setName(String name) { this.name = name; } public void setPhone(String phone) { this.phone = phone; } public void setId(int id) { this.id = id; } @Override public String toString() { return "Name: " + name + ", Phone: " + phone + ", ID: " + id; } }Address.javapublic class Address { private String street; private String city; private String state; private String zip; public Address(String street, String city, String state, String zip) { this.street = street; this.city = city; this.state = state; this.zip = zip; } public String getStreet() { return street; } public String getCity() { return city; } public String getState() { return state; } public String getZip() { return zip; } public void setStreet(String street) { this.street = street; } public void setCity(String city) { this.city = city; } public void setState(String state) { this.state = state; } public void setZip(String zip) { this.zip = zip; } @Override public String toString() { return street + ", " + city + ", " + state + " " + zip; } } -
Modify the class
Customerby adding new data member calledaddressof typeAddress. -
Add a fully parameterized constructor in the
Customerclass that initializes all fields including theaddress. -
Add a setter and a getter for the
addressdata member.
- Modify the
toString()method by adding theAddress.toString()to the returned string. - Create two
Customerobjects and set their addresses. - Test your code.
Exercise 2
Book Class
-
Add the following
BookandAuthorclasses to your project:Book.javapublic class Book { private String isbn; private String title; private double price; public Book(String isbn, String title, double price) { this.isbn = isbn; this.title = title; this.price = price; } public String getIsbn() { return isbn; } public String getTitle() { return title; } public double getPrice() { return price; } public void setIsbn(String isbn) { this.isbn = isbn; } public void setTitle(String title) { this.title = title; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return title + " [" + isbn + "]" + " $" + price; } }Author.javapublic class Author { private int id; private String firstName; private String lastName; public Author(int id, String firstName, String lastName) { this.id = id; this.firstName = firstName; this.lastName = lastName; } public int getId() { return id; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public void setId(int id) { this.id = id; } public void setFirstName(String firstName) { this.firstName = firstName; } public void setLastName(String lastName) { this.lastName = lastName; } @Override public String toString() { return lastName + ", " + firstName; } } -
Add an
authorwith typeAuthoras a new data member to theBookclass. -
Add a new
Bookconstructor. -
Add a getter and a setter for
author.
-
Use
Author’stoString()method inBook’stoString()method. -
Test your code.
-
Add the following
Publisherclass to your project:Publisher.javapublic class Publisher { private int id; private String name; private String email; public Publisher(int id, String name, String email) { this.id = id; this.name = name; this.email = email; } public int getId() { return id; } public String getName() { return name; } public String getEmail() { return email; } public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return name + "<" + email + ">"; } } -
Add an
addresswith typeAddressas a new data member of thePublisherclass. -
Add a new constructor to the
Publisherclass. -
Define a getter and a setter for
address. -
Use
Address’stoString()method inPublisher’stoString()method. -
Test your code.
-
Update the
Bookclass by adding a new data memberpublisherof typePublisher. Repeat all the steps that you did previously with the other classes. -
Test your code with proper data.
Exercise 3
A book generally contains multiple chapters. Each chapter has a name and number of pages. We will make this change to the Book class.
This time we are not going to add Chapter as a data member but instead we will add a List of Chapter objects.
-
Add the following
Chapterclass to your project:Chapter.javapublic class Chapter { private String title; private int pageCount; public Chapter(String title, int pageCount) { this.title = title; this.pageCount = pageCount; } public String getTitle() { return title; } public int getPageCount() { return pageCount; } public void setTitle(String title) { this.title = title; } public void setPageCount(int pageCount) { this.pageCount = pageCount; } @Override public String toString() { return title + " (" + pageCount + " pages)"; } } -
Add a
ListofChapters namedchaptersas a new data member. There is no need to create or modify the constructor. -
Add a setter and getter for
chapters. -
Add two methods:
void addChapter(Chapter c)andvoid removeChapter(Chapter c). Theadd()andremove()methods will make the changes directly to the list of chapters. -
Add a two methods:
int getPageCount(), that returns the total number of pages in all the chapters, andint getChapterCount(). -
Modify the
toString()method of theBookclass to display the number of chapters and the total number of pages. -
Test your code with proper data. Create a
Bookobject that has two chapters, a publisher who has an address, and an author:Address address = new Address("501 Boylston St.", "Boston", "Massachusetts", "02116"); Publisher publisher = new Publisher(1, "Addison-Wesley Professional", "[email protected]"); Author author = new Author(1, "Donald", "Knuth"); Chapter ch1 = new Chapter("Chapter 1: Basic concepts", 229); Chapter ch2 = new Chapter("Chapter 2: Information Structures", 234); Book book = new Book("978-0201896831", "The Art of Computer Programming, Vol. 1: Fundamental Algorithms", 62.49);Modify the code above and associated classes so that your output is as follows:
The Art of Computer Programming, Vol. 1: Fundamental Algorithms by Knuth, Donald Publisher: Addison-Wesley Professional <[email protected]>; 501 Boylston St., Boston, Massachusetts 02116 2 chapters, 463 pages, $62.49, [978-0201896831] -
To support multiple authors for a single book, change the
authordata member to aListofAuthors and update the constructor. You also need to add methods likeint getAuthorCount(),void addAuthor(Author a), andvoid removeAuthor(Author a).Make sure you do not add duplicate authors for a single book by preventing an author ID from being added twice. Furthermore, you need to print the list of all authors in the
toString()of theBookclass.
Exercise 4+
Hotel Application
We are going to build a mini-hotel application. The hotel has a name, a location, and a list of rooms. Rooms can be booked and released. Three types of rooms available: single, double, and suite.
-
Add the following
Locationclass to your project:Location.javapublic class Location { private String city; private String country; public Location(String city, String country) { this.city = city; this.country = country; } public String getCity() { return city; } public String getCountry() { return country; } public void setCity(String city) { this.city = city; } public void setCountry(String country) { this.country = country; } @Override public String toString() { return city + ", " + country; } } -
Add the following
Roomclass to your project:Room.javapublic class Room { private int number; private int floor; private boolean available; public Room(int number, int floor, boolean available) { this.number = number; this.floor = floor; this.available = available; } public int getNumber() { return number; } public int getFloor() { return floor; } public boolean isAvailable() { return available; } public void setNumber(int number) { this.number = number; } public void setFloor(int floor) { this.floor = floor; } public void setAvailable(boolean available) { this.available = available; } @Override public String toString() { return String.format("Room number: %d\tFloor: %d\tAvailable: %s", number, floor, (this.isAvailable() ? "Yes" : "No")); } } -
Create a
RoomTypeenumeration with three values:SINGLE,DOUBLE,SUITE. -
Make
roomType:RoomTypea field of theRoomclass. Add it to the fully parameterized constructor. -
Add a setter and getter for the
roomTypedata member. -
Modify the
toString()method of theRoomclass based on the following example:Room room = new Room(425,4, true, RoomType.DOUBLE); System.out.println(room);[DOUBLE] Room number: 425 Floor: 4 Available: Yes
Composing Classes
The Hotel class has three fields: name, location, and rooms.
-
Provide two constructors: one takes the
name, and the other takes thenameandlocation. -
Provide setters and getters for all three fields.
-
Add three private constants to the
Hotelclass:private final double SINGLE_ROOM_RATE = 355.5; private final double DOUBLE_ROOM_RATE = 515.5; private final double SUITE_RATE = 1079.5; -
Provide all the following methods:
public double getRoomRate(RoomType type): returns the rate for a given room type.public void addRoom(Room r): adds a new object to the hotel’s list of rooms.public void reserveRoom(int roomNumber): sets the room availability tofalse.public void releaseRoom(int roomNumber): sets the room availability totrue.public boolean isRoomAvailable(int roomNumber): returns room availability.public List<Room> getAvailableRooms(): returns a list of the available rooms.public int getAvailableRoomsCount(): returns the number of available rooms in the hotel’s list of rooms.public int getRoomsCount(): returns the number of all hotel rooms.public List<Room> roomsInFloor(int floorNumber): returns a list of the rooms in a specific floor number.
-
Provide a
toString()method that reuses code from all the included classes and generates a string based on the following output:Hotel: Hilton. Address: Doha, Qatar Room Count: 4 (Available: 3) Today's Income: $515.50 [DOUBLE] Room number: 425 Floor: 4 Available: No @ $515.50 [SINGLE] Room number: 423 Floor: 4 Available: Yes @ $355.50 [DOUBLE] Room number: 328 Floor: 3 Available: Yes @ $515.50 [SUITE] Room number: 218 Floor: 2 Available: Yes @ $1,079.50
Hotel Tester
-
Test your classes using the following code:
Hotel hotel = new Hotel("Hilton"); Room room1 = new Room(425, 4, true, RoomType.DOUBLE); Room room2 = new Room(423, 4, true, RoomType.SINGLE); Room room3 = new Room(328, 3, true, RoomType.DOUBLE); Room room4 = new Room(218, 2, true, RoomType.SUITE); hotel.setLocation(new Location("Doha", "Qatar")); hotel.addRoom(room1); hotel.addRoom(room2); hotel.addRoom(room3); hotel.addRoom(room4); hotel.reserveRoom(425); hotel.reserveRoom(218); System.out.println(hotel);
Booking Application
- Create a class named
BookingApplication. - The
BookingApplicationclass has two fields: a name and a list of hotels. - Discuss the usage of this application:
- What can you do with it?
- How can you benefit from the available code?
- What changes are needed to make it a fully-fledged application?