Book Image

Java EE 8 Design Patterns and Best Practices

By : Rhuan Rocha, Joao Carlos Purificação
Book Image

Java EE 8 Design Patterns and Best Practices

By: Rhuan Rocha, Joao Carlos Purificação

Overview of this book

Patterns are essential design tools for Java developers. Java EE Design Patterns and Best Practices helps developers attain better code quality and progress to higher levels of architectural creativity by examining the purpose of each available pattern and demonstrating its implementation with various code examples. This book will take you through a number of patterns and their Java EE-specific implementations. In the beginning, you will learn the foundation for, and importance of, design patterns in Java EE, and then will move on to implement various patterns on the presentation tier, business tier, and integration tier. Further, you will explore the patterns involved in Aspect-Oriented Programming (AOP) and take a closer look at reactive patterns. Moving on, you will be introduced to modern architectural patterns involved in composing microservices and cloud-native applications. You will get acquainted with security patterns and operational patterns involved in scaling and monitoring, along with some patterns involved in deployment. By the end of the book, you will be able to efficiently address common problems faced when developing applications and will be comfortable working on scalable and maintainable projects of any size.
Table of Contents (20 chapters)
Title Page
Copyright and Credits
Dedication
Packt Upsell
Contributors
Preface
5
Aspect-Oriented Programming and Design Patterns
Index

Explaining design patterns


Design patterns are sets of solutions to common design problems that occur over and over in development. They work as a solution template in which an abstract solution for a common problem is described and the user then applies it, adapting it to their problem. In object-oriented programming, the design pattern provides a way to design reusable classes and objects for a specific problem as well as defining the relationship between objects and classes. In addition, design patterns provide a common idiom among programming languages that allows architects and software developers to communicate about a common and recurring problem regardless of the programming language they are using. With this, we are able to identify a problem and its solution by the name of the pattern and thinking about a solution by a model point of view in a high abstraction level of language programming details.

The design patterns theme gained strength in 1994 after the Gang of Four (formed by Rich Gamma, Richard Helm, Ralph Johnson, and John Vlissides) wrote Design Patterns: Elements of Reusable Object‐Oriented Software. Here, they described 23 design patterns that were later known as GoF design patterns and are still used today. 

Explaining the Gang of Four design patterns

The Gang of Four (GoF) design patterns are 23 patterns that are classified as creational patterns, structural patterns, and behavioral patterns. The creational patterns control the creation and initialization of the object and class selection; the structural patterns define the relationship between classes and objects, and the behavioral patterns control the communication and interaction between objects. As well as this, the GoF design patterns have two types of scope which define the focus of solutions. These scopes areobject scope, which resolves problems about object relations, and class scope, which resolves problems about class relations. 

The object scope works with composition and the behavior changes are done in a runtime. Thus, the object can have a dynamic behavior. The class scope works with inheritance and its behavior is static-fixed at compile-time way. Then, to change the behavior of a class-scope pattern, we need to change the class and recompile.

Patterns classified as class scope solve problems about the relationship between classes and are static (fixed at compile time and cannot be changed once compiled). However, patterns classified under the object scope solve problems about the relationship between objects and can be changed at runtime.

The following diagram shows us the three classifications, as well as their patterns and scope:

 

In the preceding diagram, we can see the Factory Method pattern on the Class section and the Abstract Factory pattern on the Object section. This occurs because the Factory Methodworks with inheritance and the abstract method pattern works with composition. Then, the Factory Method is static-fixed at compile time and cannot be changed after compilation. However, the Abstract Factory is dynamic and can be changed at runtime.

GoF design patterns are generally described using a graphical notation such as a use case diagram, and an example of the implementation's code. The used notation must be able to describe the classes and objects as well as the relationship between these classes and objects. 

The pattern's name is an important part of the design patterns. This is because it is what the developer uses to quickly identify the problem related to the pattern and to understand how the pattern will solve it. The name of the pattern must be brief and refer to the problem and its solution.

A design pattern is a great tool for designing software development, but its use needs to be analyzed to determine if the design pattern is really required in order to solve the problem.

 

The catalog of Gang of Four design patterns

Names of design patterns need be succinct, making them easy to identify. This is because design patterns create a vocabulary for communicating between developers independent of programming language, permitting developers to identify problems and solutions only by name of a design pattern.

In design patterns, a catalog is a set of pattern names which are designed to permit a better communication between developers.

The catalog of GoF's design patterns has 23 patterns, as shown inthe preceding diagram. Here is a description of these patterns: 

  • Abstract Factory: This provides an interface to create objects without specifying their concrete class, making it possible to decouple the business logic and the object creation logic. With this, we can update the object creation logic in an easy way.
  • Adapter: This provides an interface that makes it possible for two incompatible interfaces to work together. The adapter pattern works as a bridge between interfaces, adapting these interfaces to work together. Furthermore, the adapter can adopt a class or objects.
  • Bridge: This pattern decouples an abstraction from its implementation, making them vary independently. With this, we can modify the implementations without impacting the abstractions and we can also modify the abstractions without impacting the implementations. The class of abstraction hides implementations and its complexity.
  • Builder: This pattern separates the construction of a complex object from its representation. With this, we can construct the objects of several representations using the same process to that. Thus, we create a standard process of construction of objects that have a complex process to construct. 
  • Chain of responsibility: This pattern avoids coupling the sender and receiver of a request creating some objects that have a chance to treat the requests. These objects create a chain of receiver objects for a sender's request. Each object of this chain receives the request and verifies whether or not it will treat this request. 
  • Command: This pattern encapsulates a request for an object and creates a wrapper of requests containing their information about the request. With this, we can do a request to some object sending parameters without knowing about this operation. Furthermore, the command permits us to execute an undo operation.
  • Composite: This pattern composes objects into a tree structure, which represents a part-whole hierarchy. It permits you to treat a group of objects as a single object.
  • Decorator: This pattern permit extends a functionality of a class with flexibility, without use subclass. It allows you to dynamically attach a new responsibility to an object.
  • Facade: This hides the complexity of the system, applying a unified interface to a set of interfaces on a subsystem. This makes the subsystem easy to use.
  • Factory Method: This defines an interface for creating an object, and the subclass states which class to initiate. 
  • Flyweight: This uses sharing to efficiently support a large number of fine-grained objects. This pattern reduces the number of objects created.
  • Interpreter: This pattern represents language grammar and uses it to interpret them as sentences of a language.
  • Iterator: This pattern provides a way to sequentially access the elements of a set of objects without knowing its underlying representation.
  • Mediator: This reduces the complexity of communication by creating an object that encapsulates all the communication and interaction between objects.
  • Memento: This pattern captures the object's internal states without hurting encapsulated concepts, with this, the state of the object can be restored by the object. This pattern works as a backup that maintains the current state of an object.
  • Observer: This defines a one-to-many dependency between objects. This means that if one object is modified, all of its dependents are automatically notified and updated.
  • Prototype: This pattern permits us to create a new object using an object or instance as a prototype. This pattern creates a copy of an object, creating a new object with the same state of the object used as a prototype. 
  • Proxy: This pattern creates a surrogate object (proxy object) for another object (original object) in order to control the access to the original object.
  • State: This permits an object to alter its behavior when its internal state changes.
  • Singleton: This ensures that a class has only one instance in the entire project, and the same instance of the object is returned every time the creation process is performed/run.
  • Strategy: This creates a family of algorithms, encapsulating each one and making them interchangeable. This pattern permits you to change the algorithm at runtime.
  • Template method: This defines a skeleton for an algorithm in an operation, and the subclass defines some steps to the algorithm. This pattern algorithm structure and the subclass redefine some steps of this algorithm without modifying its structure.
  • Visitor: This represents an operation to be performed on an object structure. This pattern permits us to add new operations to an element without modifying its class.