40,81 €
Create various design patterns to master the art of solving problems using Java
Key Features
Book Description
Having a knowledge of design patterns enables you, as a developer, to improve your code base, promote code reuse, and make the architecture more robust. As languages evolve, new features take time to fully understand before they are adopted en masse. The mission of this book is to ease the adoption of the latest trends and provide good practices for programmers.
We focus on showing you the practical aspects of smarter coding in Java. We'll start off by going over object-oriented (OOP) and functional programming (FP) paradigms, moving on to describe the most frequently used design patterns in their classical format and explain how Java's functional programming features are changing them.
You will learn to enhance implementations by mixing OOP and FP, and finally get to know about the reactive programming model, where FP and OOP are used in conjunction with a view to writing better code. Gradually, the book will show you the latest trends in architecture, moving from MVC to microservices and serverless architecture. We will finish off by highlighting the new Java features and best practices. By the end of the book, you will be able to efficiently address common problems faced while developing applications and be comfortable working on scalable and maintainable projects of any size.
What you will learn
Who this book is for
This book is for those who are familiar with Java development and want to be in the driver's seat when it comes to modern development techniques. Basic OOP Java programming experience and elementary familiarity with Java is expected.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 284
Veröffentlichungsjahr: 2018
Copyright © 2018 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the authors, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Commissioning Editor: Kunal ParikhAcquisition Editor: Alok DhuriContent Development Editor: Nikhil BorkarTechnical Editor: Jash BavishiCopy Editor: Safis EditingProject Coordinator: Ulhas KambaliProofreader: Safis EditingIndexer: Rekha NairGraphics: Tania DuttaProduction Coordinator: Arvindkumar Gupta
First published: June 2018
Production reference: 1250618
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-78646-359-3
www.packtpub.com
Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Mapt is fully searchable
Copy and paste, print, and bookmark content
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.
Kamalmeet Singh got his first taste of programming at the age of 15, and he immediately fell in love with it. After getting his bachelor’s degree in information technology, he joined a start-up, and his love for Java programming grew further. After spending over 13 years in the IT industry and working in different companies, countries, and domains, Kamal has matured into an ace developer and a technical architect. The technologies he works with include cloud computing, machine learning, augmented reality, serverless applications, microservices, and more, but his first love is still Java.
Adrian Ianculescu is a software developer with 20 years of programming experience, of which 12 years were in Java, starting with C++, then working with C#, and moving naturally to Java. Working in teams ranging from 2 to 40, he realized that making software is not only about writing code, and became interested in software design and architecture, in different methodologies and frameworks. After living the corporate life for a while, he started to work as a freelancer and entrepreneur, following his childhood passion to make games.
Lucian-Paul Torje is an aspiring software craftsman who has been working in the software industry for almost 15 years. He is interested in almost anything that has to do with technology. This is why he has worked with everything from MS-DOS TSR to microservices, from Atmel microcontrollers to Android, iOS, and Chromebooks, from C/C++ to Java, and from Oracle to MongoDB. Whenever someone is needed to use new and innovative approaches to solve a problem, he is keen to give it a go!
Aristides Villarreal Bravo is a Java developer, a member of the NetBeans Dream Team, and a Java User Groups leader. He lives in Panama. He has organized and participated in various conferences and seminars related to Java, JavaEE, NetBeans, the NetBeans platform, free software, and mobile devices. He is the author of jmoordb and tutorials and blogs about Java, NetBeans, and web development.
Aristides has participated in several interviews on sites about topics such as NetBeans, NetBeans DZone, and JavaHispano. He is a developer of plugins for NetBeans.
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Title Page
Copyright and Credits
Design Patterns and Best Practices in Java
Packt Upsell
Why subscribe?
PacktPub.com
Contributors
About the authors
About the reviewer
Packt is searching for authors like you
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Download the color images
Conventions used
Get in touch
Reviews
From Object-Oriented to Functional Programming
Java – an introduction
Java programming paradigms
Imperative programming
Real-life imperative example
Object-oriented paradigm
Objects and classes
Encapsulation
Abstraction
Inheritance
Polymorphism
Declarative programming
Functional programming
Working with collections versus working with streams
An introduction to Unified Modeling Language
Class relations
Generalization
Realization
Dependency
Association
Aggregation
Composition
Design patterns and principles
Single responsibility principle
Open/closed principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency inversion principle
Summary
Creational Patterns
Singleton pattern
Synchronized singletons
Synchronized singleton with double-checked locking mechanism
Lock-free thread-safe singleton
Early and lazy loading
The factory pattern
Simple factory pattern
Static factory
Simple factory with class registration using reflection
Simple factory with class registration using Product.newInstance
Factory method pattern
Anonymous concrete factory
Abstract factory
Simple factory versus factory method versus abstract factory
Builder pattern
Car builder example
Simplified builder pattern
Anonymous builders with method chaining
Prototype pattern
Shallow clone versus deep clone
Object pool pattern
Summary
Behavioral Patterns
The chain-of-responsibility pattern
Intent
Implementation
Applicability and examples
The command pattern
Intent
Implementation
Applicability and examples
The interpreter pattern
Intent
Implementation
Applicability and examples
The iterator pattern
Intent
Implementation
Applicability and examples
The observer pattern
Intent
Implementation
The mediator pattern
Intent
Implementation
Applicability and examples
The memento pattern
Intent
Implementation
Applicability
The state pattern
The strategy pattern
Intent
Implementation
The template method pattern
Intent
Implementation
The null object pattern
Implementation
The visitor pattern
Intent
Implementation
Summary
Structural Patterns
Adapter pattern
Intent
Implementation
Examples
Proxy pattern
Intent
Implementation
Examples
Decorator pattern
Intent
Implementation
Examples
Bridge pattern
Intent
Implementation
Examples
Composite pattern
Intent
Implementation
Examples
Façade pattern
Intent
Implementation
Examples
Flyweight pattern
Intent
Implementation
Examples
Summary
Functional Patterns
Introducing functional programming
Lambda expressions
Pure functions
Referential transparency
First-class functions
Higher-order functions
Composition
Currying
Closure
Immutability
Functors
Applicatives
Monads
Introducing functional programming in Java
Lambda expressions
Streams
Stream creator operations
Stream intermediate operations
Stream terminal operations
Re-implementing OOP design patterns
Singleton
Builder
Adapter
Decorator
Chain of responsibility
Command
Interpreter
Iterator
Observer
Strategy
Template method
Functional design patterns
MapReduce
Intent
Examples
Loan pattern
Intent
Examples
Tail call optimization
Intent
Examples
Memoization
Intent
Examples
The execute around method
Intent
Examples
Summary
Let's Get Reactive
What is reactive programming?
Introduction to RxJava
Installing the RxJava framework
Maven installation
JShell installation
Observables, Flowables, Observers, and Subscriptions
Creating Observables
The create operator
The defer operator
The empty operator
The from operator
The interval operator
The timer operator
The range operator
The repeat operator
Transforming Observables
The subscribe operator
The buffer operator
The flatMap operator
The groupBy operator
The map operator
The scan operator
The window operator
Filtering Observables
The debounce operator
The distinct operator
The elementAt operator
The filter operator
The first/last operator
The sample operator
The skip operator
The take operator
Combining Observables
The combine operator
The join operator
The merge operator
The zip operator
Error handling
The catch operator
The do operator
The using operator
The retry operator
Schedulers
Subjects
Example project
Summary
Reactive Design Patterns
Patterns for responsiveness
Request-response pattern
Asynchronous-communication pattern
Caching pattern
Fan-out and quickest-reply pattern
Fail-fast pattern
Patterns for resilience
The circuit-breaker pattern
Failure-handling pattern
Bounded-queue pattern
Monitoring patterns
Bulkhead pattern
Patterns for elasticity
Single responsibility pattern
Stateless-services pattern
Autoscaling pattern
Self-containment pattern
Patterns for message-driven implementation
Event-driven communication pattern
Publisher-subscriber pattern
Idempotency pattern
Summary
Trends in Application Architecture
What is application architecture?
Layered architecture
Layered architecture with an example
Tiers versus layers
What does layered architecture guarantee?
What are the challenges with layered architecture?
Model View Controller architecture
MVC architecture with an example
A more contemporary MVC implementation
What does MVC architecture guarantee?
What are the challenges with MVC architecture?
Service-oriented architecture
Service-oriented architecture with an example
Web services
SOAP versus REST
Enterprise service bus
What does service-oriented architecture guarantee?
What are the challenges with service-oriented architecture?
Microservices-based Architecture
Microservice architecture with an example
Communicating among services
What does microservices-based architecture guarantee?
What are challenges with microservices-based architecture?
Serverless architecture
Serverless architecture with an example
Independence from infrastructure planning
What does serverless architecture guarantee?
What are the challenges with serverless architecture?
Summary
Best Practices in Java
A brief history of Java
Features of Java 5
Features of Java 8
Currently supported versions of Java
Best practices and new features of Java 9
Java platform module system
JShell
Private methods in interfaces
Enhancements in streams
Creating immutable collections
Method addition in arrays
Additions to the Optional class
New HTTP client
Some more additions to Java 9
Best practices and new features of Java 10
Local variable type inference
copyOf method for collections
Parallelization of full garbage collection
Some more additions to Java 10
What should be expected in Java 11?
Summary
Other Books You May Enjoy
Leave a review - let other readers know what you think
Having knowledge of design patterns enables you as a developer to improve your code base, promote code reuse, and make the architecture more robust. As languages evolve, it takes time for new features to be fully understood before they are adopted en masse. The mission of this book is to ease the adoption of the latest trends and provide good practices for programmers.
This book is for every Java developer who wants to write quality code. This book talks about a lot of best practices that quite often are missed by developers while coding. The book also covers many design patterns. Design patterns are nothing but best practices to solve particular problems that have been tried and tested by a developer community.
Chapter 1, From Object-Oriented to Functional Programming, gives an introduction to different programming paradigms associated with the Java language.
Chapter 2, Creational Patterns, introduces the first in a series of design patterns; that is, creational patterns. The chapter talks about various creational design patterns.
Chapter 3, Behavioral Patterns, talks about behavioral design patterns. It explains various design patterns to manage behavior of code and objects.
Chapter 4, Structural Patterns, introduces you to structural design patterns and explains various widely used design patterns to manage the structuring of objects.
Chapter 5, Functional Patterns, introduces readers to functional programming and patterns associated with it.
Chapter 6, Let's Get Reactive, introduces you to reactive programming and Java's implementation of it with examples.
Chapter 7, Reactive Design Patterns, further explores the pillars of reactive programming and design patterns associated with these pillars.
Chapter 8, Trends in Application Architecture – from MVC to Microservices and Serverless Applications, explores architectural patterns that have been tried and tested by developers over the years.
Chapter 9, Best Practices in Java, introduces us to the history of Java, best practices, and updates available in the latest versions of Java, and, finally, what is expected in future from Java.
Readers with prior Java experience will be able to gain the most from this book. It is recommended that readers try to explore and play around with the code examples provided in various chapters.
You can download the example code files for this book from your account at www.packtpub.com. If you purchased this book elsewhere, you can visit www.packtpub.com/support and register to have the files emailed directly to you.
You can download the code files by following these steps:
Log in or register at
www.packtpub.com
.
Select the
SUPPORT
tab.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box and follow the onscreen instructions.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR/7-Zip for Windows
Zipeg/iZip/UnRarX for Mac
7-Zip/PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Design-Patterns-and-Best-Practices-in-Java. In case there's an update to the code, it will be updated on the existing GitHub repository.
We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it from http://www.packtpub.com/sites/default/files/downloads/DesignPatternsandBestPracticesinJava_ColorImages.pdf.
There are a number of text conventions used throughout this book.
CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "Make the getInstance method thread-safe by adding the synchronized keyword to its declaration."
A block of code is set as follows:
public class Car extends Vehicle{ public Car(String name) { super(name) }}
Any command-line input or output is written as follows:
java --list-modules
Bold: Indicates a new term, an important word, or words that you see onscreen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "Before this change, you would need the complete Java Runtime Environment (JRE) as a whole to be loaded on a server or a machine to run the Java application."
Feedback from our readers is always welcome.
General feedback: Email [email protected] and mention the book title in the subject of your message. If you have questions about any aspect of this book, please email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the Internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packtpub.com.
The objective of this chapter is to introduce the reader to the fundamental concepts of writing robust, maintainable, and extendable code using design patterns and the latest features available in Java. In order to achieve our objective, we will cover the following topics:
What are programming paradigms?
Imperative paradigm
Declarative and functional paradigms
Object-oriented paradigm
An overview of Unified Modeling Language
Object-oriented design principles
In 1995, a new programming language was released, inspired by the well-known C++ and the lesser known Smalltalk. Java was the name of this new language, and it tried to fix most of the limitations its predecessors had. For example, one important feature of Java that made it popular was write once and run anywhere; that is, you could develop your code on a Windows machine and run it on a Linux or any other machine, all you needed was a JVM. It provided additional features such as garbage collection, which freed up the developer from needing to maintain memory allocation and deallocations; the Just in Time compiler (JIT) made Java intelligent and fast, and removing features such as pointers made it more secure. All the aforementioned features and the later addition of web support made Java a popular choice among developers. Around 22 years later, in a world where new languages come and disappear in a couple of years, Java version 10 has already been successfully launched and adapted by the community, which says a lot about the success of Java.
What are programming paradigms? Since software development began, there have been different approaches to designing programing languages. For each programming language, we have a set of concepts, principles, and rules. Such a set of concepts, principles, and rules is called a programming paradigm. In theory, languages are considered to fall under one paradigm only, but, in practice, programming paradigms are mostly combined in one language.
In the following section, we will highlight the programming paradigms on which Java programming language is based, along with the major concepts that describe these paradigms. These are imperative, object-oriented, declarative, and functional programming.
Imperative programming is a programming paradigm in which statements are written to change the state of the program. This concept emerged at the beginning of computing and is very close to the computer's internal structure. The program is a set of instructions that is run on the processing unit, and it changes the state (which is stored as variables in the memory) in an imperative manner. The name imperative implies the fact that the instructions that are executed dictate how the program operates.
Most of the most popular programming languages today are based, more or less, on the imperative paradigm. The best example of a mainly imperative language is C.
In order to better understand the concept of the imperative programming paradigm, let's take the following example: you're meeting a friend for a hackathon in your town, but he has no idea how to get there. We'll explain to him how to get there in an imperative way:
From the Central Station, take tram 1.
Get off the tram at the third station.
Walk to the right, toward Sixth Avenue, until you reach the third junction.
The object-oriented paradigm is often associated with imperative programming, but, in practice, both functional and object-oriented paradigms can coexist. Java is living proof that supports this collaboration.
In the following section, we will briefly highlight the main object-oriented concepts as they are implemented in the Java language.
Objects are the main elements of an object-oriented programming (OOP) language. An object holds both the state and the behavior.
If we think of classes as a template, objects are the implementation of the template. For example, if human is a class that defines the behavior and properties that a human being can have, you and I are objects of this human class, as we have fulfilled all the requirements of being a human. Or, if we think of car as a class, a particular Honda Civic car will be an object of this class. It will fulfill all the properties and behaviors that a car has, such as it has an engine, a steering wheel, headlights, and so on, and it has behaviors of moving forward, moving backward, and so on. We can see how the object-oriented paradigm can relate to the real world. Almost everything in the real world can be thought of in terms of classes and objects, hence it makes OOP effortless and popular.
Object-oriented programming is based on four fundamental principles:
Encapsulation
Abstraction
Inheritance
Polymorphism (subtyping polymorphism).
Encapsulation basically means the binding of attributes and behaviors. The idea is to keep the properties and behavior of an object in one place, so that it is easy to maintain and extend. Encapsulation also provides a mechanism to hide unnecessary details from the user. In Java, we can provide access specifiers to methods and attributes to manage what is visible to a user of the class, and what is hidden.
Encapsulation is one of the fundamental principles of object-oriented languages. It helps in the decoupling of different modules. Decoupled modules can be developed and maintained more or less independently. The technique through which decoupled modules/classes/code are changed internally without affecting their external exposed behavior is called code refactoring.
Abstraction is closely related to encapsulation, and, to some extent, it overlaps with it. Briefly, abstraction provides a mechanism that exposes what an object does and hides how the object does what it's supposed to do.
A real-world example of abstraction is a car. In order to drive a car, we don't really need to know what the car has under the hood, but we need to know the data and behavior it exposes to us. The data is exposed on the car's dashboard, and the behavior is represented by the controls we can use to drive a car.
Inheritance is the ability to base an object or class on another one. There is a parent or base class, which provides the top-level behavior for an entity. Every subclass entity or child class that fulfills the criteria to be a part of the parent class can inherit from the parent class and add additional behavior as required.
Let's take a real-world example. If we think of a Vehicle as a parent class, we know a Vehicle can have certain properties and behaviors. For example, it has an engine, doors, and so on, and behavior-wise it can move. Now all entities that fulfill these criteria—for example, Car, Truck, Bike, and so on—can inherit from Vehicle and add on top of given properties and behavior. In other words, we can say that a Car is a type of Vehicle.
Let's see how this will look as code; we will first create a base class named Vehicle. The class has a single constructor, which accepts a String (the vehicle name):
public class Vehicle { private Stringname; public Vehicle(Stringname) { this.name=name; }}
Now we can create a Car class with a constructor. The Car class is derived from the Vehicle class, so it inherits and can access all the members and methods declared as protected or public in the base class:
public class Car extends Vehicle{ public Car(String name) { super(name) }}
Let's go back to the real-life imperative example, where we gave directions to a friend on how to get to a place. When we think in terms of the declarative programming paradigm, instead of telling our friend how to get to the specific location, we can simply give him the address and let him figure out how to get there. In this case, we tell him what to do and we don't really care if he uses a map or a GPS, or if he asks somebody for instructions: Be at the junction between Fifth Avenue and Ninth Avenue at 9:30 in the morning.
As opposed to imperative programming, declarative programming is a programming paradigm that specifies what a program should do, without specifying how to do it. Among the purely declarative languages are database query languages, such as SQL and XPath, and regular expressions.
Declarative programming languages are more abstract compared to imperative ones. They don't mimic the hardware structure, and, as a consequence, they don't change the programs' states but transform them to new states, and are closer to mathematical logic.
In general, the programming styles that are not imperative are considered to fall in the declarative category. This is why there are many types of paradigms that fall under the declarative category. In our quest, we will look at the only one that is relevant to the scope of our journey: functional programming.
Functional programming is a sub-paradigm of declarative programming. As opposed to imperative programming, functional programming does not change the internal state of the program.
In imperative programming, the functions can be regarded more as sequences of instructions, routines, or procedures. They not only depend on the state stored in the memory but can also change that state. This way, invoking an imperative function with the same arguments can produce different results depending on the current program's state, and at the same time, the executed function can change the program's variables.
In functional programming terminology, functions are similar to mathematical functions, and the output of a function depends only on its arguments, regardless of the program's state, which, at the same time, remains unaffected by the execution of the function.
Paradoxically, while imperative programming has existed since computers were first created, the basic concepts of functional programming dates back before that. Most functional languages are based on lambda calculus, a formal system of mathematical logic created in the 1930s by mathematician Alonzo Church.
One of the reasons why functional languages become so popular in those days is the fact that they can easily run in parallel environments. This should not be confused with multithreading. The main feature that allows functional languages to run in parallel is the basic principle on which they reside: the functions rely only on the input arguments and not on the program's state. That is, they can be run anywhere, and the results of the multiple parallel executions are then joined and used further.
Unified Modeling Language (UML) is a modeling language that helps us to represent how the software is structured; how different modules, classes, and objects interact with each other, and what the relations between them are.
UML is frequently used in association with object-oriented design, but it has a much broader scope. However, that is beyond the scope of this book, so, in the next sections, we will highlight the UML features relevant to this book.
In UML, we can define the structure and behavior of a system, and we can visualize the model or parts of it through diagrams. There are two types of diagram:
Structure diagrams are used to represent the structure of a system. There are many types of structure diagrams, but we are only interested in class diagrams. object, package, and component diagrams are similar to class diagrams.
Behavior diagrams are used to describe the behavior of a system. Interaction diagrams are a subset of behavior diagrams and are used to describe the flow of control and data among different components of a system. Among the behavior diagrams, the sequence diagram is used extensively in object-oriented design.
Class diagrams are the type of diagrams used most in object-oriented design and development stages. They are a type of structure diagram, and are used to illustrate the structure of classes and the relations among them:
