mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-08-05 12:23:29 +00:00
* #1842 Setting up project and creating example classes. Issues running site and deploy * #1842 Added unit tests * #1842 Improved example * #1842 Added UML class diagram * #1842 Added comments to Genre class * #1842 Improved readability of lambda function * #1842 Started working on the README and created initial UML * #1842 Added example to README * #1842 Replaced prints with LOGGER * #1842 Fixed typo in README * #1842 Testing commit account * #1842 Adding documentation to App class * #1842 Improved documentation * #1842 Added documentation to AppTest * #1842 Fixing latex formating issue * #1842 Improving the intent description * #1842 Removed override methods from the UML diagram for clarity * #1842 Renamed the SCI_FI enum * #1842 Updated the currying pom.xml * #1842 Removed unneeded comment * #1842 Improving documentation and README * Added review changes. * Fixing build issues and added javadoc comments to functional interfaces. * Removing code smells * Removed unnecessary toString method * Using lombok to reduce boiler plate. * Fixed frontmatter. * Removing function name code smell * Fixed README typo * Added book_creator test to improve coverage Co-authored-by: Hugo Kat <u7286091@anu.edu.au>
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.currying;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Currying decomposes a function with multiple arguments in multiple functions that
|
||||
* take a single argument. A curried function which has only been passed some of its
|
||||
* arguments is called a partial application. Partial application is useful since it can
|
||||
* be used to create specialised functions in a concise way.
|
||||
*
|
||||
* <p>In this example, a librarian uses a curried book builder function create books belonging to
|
||||
* desired genres and written by specific authors.
|
||||
*/
|
||||
@Slf4j
|
||||
public class App {
|
||||
/**
|
||||
* Main entry point of the program.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
LOGGER.info("Librarian begins their work.");
|
||||
|
||||
// Defining genre book functions
|
||||
Book.AddAuthor fantasyBookFunc = Book.builder().withGenre(Genre.FANTASY);
|
||||
Book.AddAuthor horrorBookFunc = Book.builder().withGenre(Genre.HORROR);
|
||||
Book.AddAuthor scifiBookFunc = Book.builder().withGenre(Genre.SCIFI);
|
||||
|
||||
// Defining author book functions
|
||||
Book.AddTitle kingFantasyBooksFunc = fantasyBookFunc.withAuthor("Stephen King");
|
||||
Book.AddTitle kingHorrorBooksFunc = horrorBookFunc.withAuthor("Stephen King");
|
||||
Book.AddTitle rowlingFantasyBooksFunc = fantasyBookFunc.withAuthor("J.K. Rowling");
|
||||
|
||||
// Creates books by Stephen King (horror and fantasy genres)
|
||||
Book shining = kingHorrorBooksFunc.withTitle("The Shining")
|
||||
.withPublicationDate(LocalDate.of(1977, 1, 28));
|
||||
Book darkTower = kingFantasyBooksFunc.withTitle("The Dark Tower: Gunslinger")
|
||||
.withPublicationDate(LocalDate.of(1982, 6, 10));
|
||||
|
||||
// Creates fantasy books by J.K. Rowling
|
||||
Book chamberOfSecrets = rowlingFantasyBooksFunc.withTitle("Harry Potter and the Chamber of Secrets")
|
||||
.withPublicationDate(LocalDate.of(1998, 7, 2));
|
||||
|
||||
// Create sci-fi books
|
||||
Book dune = scifiBookFunc.withAuthor("Frank Herbert")
|
||||
.withTitle("Dune")
|
||||
.withPublicationDate(LocalDate.of(1965, 8, 1));
|
||||
Book foundation = scifiBookFunc.withAuthor("Isaac Asimov")
|
||||
.withTitle("Foundation")
|
||||
.withPublicationDate(LocalDate.of(1942, 5, 1));
|
||||
|
||||
LOGGER.info("Stephen King Books:");
|
||||
LOGGER.info(shining.toString());
|
||||
LOGGER.info(darkTower.toString());
|
||||
|
||||
LOGGER.info("J.K. Rowling Books:");
|
||||
LOGGER.info(chamberOfSecrets.toString());
|
||||
|
||||
LOGGER.info("Sci-fi Books:");
|
||||
LOGGER.info(dune.toString());
|
||||
LOGGER.info(foundation.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.currying;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
/**
|
||||
* Book class.
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class Book {
|
||||
private final Genre genre;
|
||||
private final String author;
|
||||
private final String title;
|
||||
private final LocalDate publicationDate;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Book book = (Book) o;
|
||||
return Objects.equals(author, book.author)
|
||||
&& Objects.equals(genre, book.genre)
|
||||
&& Objects.equals(title, book.title)
|
||||
&& Objects.equals(publicationDate, book.publicationDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(author, genre, title, publicationDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Book{" + "genre=" + genre + ", author='" + author + '\''
|
||||
+ ", title='" + title + '\'' + ", publicationDate=" + publicationDate + '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Curried book builder/creator function.
|
||||
*/
|
||||
static Function<Genre, Function<String, Function<String, Function<LocalDate, Book>>>> book_creator
|
||||
= bookGenre
|
||||
-> bookAuthor
|
||||
-> bookTitle
|
||||
-> bookPublicationDate
|
||||
-> new Book(bookGenre, bookAuthor, bookTitle, bookPublicationDate);
|
||||
|
||||
/**
|
||||
* Implements the builder pattern using functional interfaces to create a more readable book
|
||||
* creator function. This function is equivalent to the BOOK_CREATOR function.
|
||||
*/
|
||||
public static AddGenre builder() {
|
||||
return genre
|
||||
-> author
|
||||
-> title
|
||||
-> publicationDate
|
||||
-> new Book(genre, author, title, publicationDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface which adds the genre to a book.
|
||||
*/
|
||||
public interface AddGenre {
|
||||
Book.AddAuthor withGenre(Genre genre);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface which adds the author to a book.
|
||||
*/
|
||||
public interface AddAuthor {
|
||||
Book.AddTitle withAuthor(String author);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface which adds the title to a book.
|
||||
*/
|
||||
public interface AddTitle {
|
||||
Book.AddPublicationDate withTitle(String title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface which adds the publication date to a book.
|
||||
*/
|
||||
public interface AddPublicationDate {
|
||||
Book withPublicationDate(LocalDate publicationDate);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.currying;
|
||||
|
||||
/**
|
||||
* Enum representing different book genres.
|
||||
*/
|
||||
public enum Genre {
|
||||
FANTASY,
|
||||
HORROR,
|
||||
SCIFI;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.currying;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests that the App can be run without throwing any exceptions.
|
||||
*/
|
||||
class AppTest {
|
||||
@Test
|
||||
void executesWithoutExceptions() {
|
||||
assertDoesNotThrow(() -> App.main(new String[]{}));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.currying;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* Unit tests for the Book class
|
||||
*/
|
||||
class BookCurryingTest {
|
||||
private static Book expectedBook;
|
||||
|
||||
@BeforeAll
|
||||
public static void initialiseBook() {
|
||||
expectedBook = new Book(Genre.FANTASY,
|
||||
"Dave",
|
||||
"Into the Night",
|
||||
LocalDate.of(2002, 4, 7));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the expected book can be created via curried functions
|
||||
*/
|
||||
@Test
|
||||
void createsExpectedBook() {
|
||||
Book builderCurriedBook = Book.builder()
|
||||
.withGenre(Genre.FANTASY)
|
||||
.withAuthor("Dave")
|
||||
.withTitle("Into the Night")
|
||||
.withPublicationDate(LocalDate.of(2002, 4, 7));
|
||||
|
||||
Book funcCurriedBook = Book.book_creator
|
||||
.apply(Genre.FANTASY)
|
||||
.apply("Dave")
|
||||
.apply("Into the Night")
|
||||
.apply(LocalDate.of(2002, 4, 7));
|
||||
|
||||
assertEquals(expectedBook, builderCurriedBook);
|
||||
assertEquals(expectedBook, funcCurriedBook);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that an intermediate curried function can be used to create the expected book
|
||||
*/
|
||||
@Test
|
||||
void functionCreatesExpectedBook() {
|
||||
Book.AddTitle daveFantasyBookFunc = Book.builder()
|
||||
.withGenre(Genre.FANTASY)
|
||||
.withAuthor("Dave");
|
||||
|
||||
Book curriedBook = daveFantasyBookFunc.withTitle("Into the Night")
|
||||
.withPublicationDate(LocalDate.of(2002, 4, 7));
|
||||
|
||||
assertEquals(expectedBook, curriedBook);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user