Skip to content

Instantly share code, notes, and snippets.

@jjangga0214
Last active November 5, 2017 14:49
Show Gist options
  • Save jjangga0214/80ba5be5970ce4170b63f151c3e7635c to your computer and use it in GitHub Desktop.
Save jjangga0214/80ba5be5970ce4170b63f151c3e7635c to your computer and use it in GitHub Desktop.
package io.week8;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import io.week8.Library.LibraryBook;
public class LibraryDemo {
public static void main(String[] args) {
// 도서관 객체를 만들고 3개의 책을 비치한다.
Library demoLibrary = new Library("demoLibrary");
// 제목이 A인 책을 더함
demoLibrary.addBook(new LibraryBook("A"));
// 제목이 B인 책을 더함
demoLibrary.addBook("B");
demoLibrary.addBook(new LibraryBook("C"));
demoLibrary.printAllBooks();
demoLibrary.printAllRentedBooks();
// 이름이 A인 책을 모두 빌린다.
List<LibraryBook> booksRentedByMeNow = demoLibrary.rentBooks("A");
demoLibrary.printAllBooks();
demoLibrary.printAllRentedBooks();
// 책을 반납한다.
// 현재 상황에서는 아래의 2가지 방법이 모두 같은 효과를 지닌다.
LibraryBook bookToReturn = booksRentedByMeNow.isEmpty() ? new LibraryBook("A") : booksRentedByMeNow.get(0);
// 반납 방법 1 : Book 객체를 직접 넘긴다.
demoLibrary.returnRentedBook(bookToReturn);
// 반납 방법 2 : book의 이름을 넘긴다.
demoLibrary.returnRentedBook("A");
demoLibrary.printAllBooks();
demoLibrary.printAllRentedBooks();
}
}
class Library {
private String name;
// 각 도서관 인스턴스에 따라 다른 값을 가지지 않고, 클래스 차원에서 하나의 값을 가지므로 static 으로 선언
public static String hour = "9AM to 5PM";
private LibraryBook[] books;
private int nextIndex = 0;
// 개인적으로는 도서관마다 책의 권수가 다를 수도 있다고 생각하지만 무조건 10으로 하라길래 인스턴스 변수 대신 상수로 선언했다.
public static final int LIBRARY_SIZE = 10;
/**
* 도서관의 책들을 나타내는 LibraryBook 클래스는 Library의 내부에 내부 클래스로서 선언했다. 내부 클래스로 선언함으로서
* 렌트처리를 Library 클래스 내부에서만 처리 가능하도록 할수 있는 효과가 생긴다. 물론 Book을 상속한 LibraryBook 클래스를
* 내부클래스로 만드는 대신 그냥 Book을 렌트처리 할 수도 있지만, 렌트되었는지 아닌지의 여부를 Book 외부에 놓고 싶지 않고 각 책의
* 속성으로 관리하고 싶어서 자식클래스로 구현했다. 지금 상황에서는 논리적으로 LibraryBook은 각 Library 인스턴스에 종속적인
* 특징은 가지지 않으므로 static 으로 선언했다
*/
public static class LibraryBook extends Book {
private boolean isRented = false;
// 도서관 내부에서만
public LibraryBook(String name) {
super(name);
}
public boolean isRented() {
return isRented;
}
// 외부에서 반납처리를 할수 없고 오직 Library 클래스 또는 LibraryBook 클래스 안에서만 반납처리 가능하게 private 으로
// 선언한다.
private void setRented(boolean isRented) {
this.isRented = isRented;
}
// 논리적으로 super.name 속성으로만 equals를 판단하면 되기 때문에
// 여기서는 hashcode만 재정의하고 equals는 오버라이딩 하지 않고 부모 클래스의 것으로 쓰도록 한다.
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (isRented ? 1231 : 1237);
return result;
}
@Override
public String toString() {
return "LibraryBook [isRented=" + isRented + ", name=" + getName() + "]";
}
}
public Library(String name) {
this.name = name;
this.books = new LibraryBook[LIBRARY_SIZE];
}
// 메서드 오버로딩
public void addBook(LibraryBook book) {
if (nextIndex < this.books.length)
this.books[nextIndex++] = book;
}
// 메서드 오버로딩
public void addBook(String bookname) {
this.addBook(new LibraryBook(bookname));
}
public void printAllBooks() {
System.out.println("모든 책들 목록입니다.");
// System.out.println(Arrays.toString(this.books));// 주석처리된 왼쪽의 방법대로 하면 null도 같이
// 출력된다.
Arrays.stream(this.books) // this.books의 스트림[쉽게말해 자료들의 흐름. 리스트와 비슷]을 형성한다.
.filter(book -> book != null) // null이 아닌 책들만 필터링한다.
.forEach(System.out::println); // 필터링된 책들을 모두 출력한다.
}
public void printAllRentedBooks() {
System.out.println("빌려간 책들 목록입니다. (아래에 아무것도 출력되지 않으면 빌려간 책이 없는 것임)");
Arrays.stream(this.books) // this.books의 스트림[쉽게말해 자료들의 흐름. 리스트와 비슷]을 형성한다.
.filter(book -> book != null) // null이 아닌 책들만 필터링한다.
.filter(LibraryBook::isRented) // 렌트된 책들만 필터링한다.
.forEach(System.out::println); // 필터링된 책들을 모두 출력한다.
}
public List<LibraryBook> rentBooks(String bookname) {
List<LibraryBook> booksToRent = Arrays.stream(this.books) // this.books의 스트림[쉽게말해 자료들의 흐름. 리스트와 비슷]을 형성한다.
.filter(book -> book != null) // null이 아닌 책들만 필터링한다.
.filter(book -> !book.isRented()) // 렌트되지 않은 책들만 필터링한다.
.filter(book -> book.getName().equals(bookname)) // 이름이 bookname과 같은 값인 책들만 필터링한다..
.peek(book -> book.setRented(true)) // 필터링된 책들을 모두 rent 처리한다.
.collect(Collectors.toList()); // 필터링된 책들을 List로 묶는다.
return booksToRent;
}
// 메서드 오버로딩
public void returnRentedBook(LibraryBook book) {
book.setRented(false);
}
// 메서드 오버로딩
public void returnRentedBook(String bookname) {
Arrays.stream(this.books) // this.books의 스트림[쉽게말해 자료들의 흐름. 리스트와 비슷]을 형성한다.
.filter(book -> book != null) // null이 아닌 책들만 필터링한다.
.filter(book -> book.getName().equals(bookname)) // 이름이 bookname과 같은 값인 책들만 필터링한다..
.forEach(book -> book.setRented(false)); // 필터링된 책들을 모두 반납 처리한다.
}
}
class Book {
private final String name;
public Book(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Book other = (Book) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "Book [name=" + name + "]";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment