Book Image

Design Patterns and Best Practices in Java

By : Kamalmeet Singh, Adrian Ianculescu, Lucian-Paul Torje
Book Image

Design Patterns and Best Practices in Java

By: Kamalmeet Singh, Adrian Ianculescu, Lucian-Paul Torje

Overview of this book

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.
Table of Contents (15 chapters)
Title Page
Packt Upsell
Contributors
Preface
Index

An introduction to Unified Modeling Language


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:

Class diagrams are useful for describing how the classes are structured in an application. Most of the time, just looking at the structure can be enough to be able to understand how the classes interact, but sometimes this is not enough. For those cases, we can use behavior and interaction diagrams, of which the sequence diagram is used to describe class and object interaction. Let's use a sequence diagram to show how the Car and Vehicle objects interact in the inheritance and polymorphism example:

Class relations

In object-oriented programming, besides the inheritance relation that represents one of the fundamental concepts, there are a few other class relations that help us to model and develop complex software systems:

  • Generalization and realization
  • Dependency
  • Association, aggregation, and composition

Generalization

Inheritance is also called an is-a relationship because the class inherited from another class can be used as the superclass.

When a class represents the shared characteristics of more than one class, it is called a generalization; for example, Vehicle is a generalization of Bike, Car, and Truck. Similarly, when a class represents a special instance of a general class, it is called a specialization, so a Car is a specialization of Vehicle, as shown in the following diagram:

In UML terminology, the relation to describe inheritance is called Generalization.

Realization

If generalization is the corresponding term in UML for object-oriented inheritance, realization, in UML, represents the implementation of an interface by a class in object-oriented programming.

Let's assume we create an interface called Lockable, which is implemented only by Vehicles that can be locked. In this case, a version of the previous diagram implementing Lockable for the Car class will look like this:

Dependency

Dependency is one of the most generic types of UML relationship. It is used to define that one class depends in some way or other on another class, while the other class may or may not depend on the first one. A dependent relationship is used to represent relations that do not fall into one of the cases described in the following sections. Dependency is sometimes called Uses-A relationship.

In general, in object-oriented programming languages dependency is used to describe whether one class contains a parameter of the second class in the signature of a method, or whether it creates instances of the second class by passing them to other classes without using them (without invoking its methods):

Association

An association represents the relationship between two entities. There are two types of association, namely composition and aggregation. In general, an association is represented by an arrow, as shown in the following diagram:

Aggregation

An aggregation is a special type of association. If inheritance is considered to be the is-a relationship, aggregation can be considered to be the HAS-A relationship.

Aggregation is used to describe a relation between two or more classes, when one class contains the other from a logical point of view, but instances of the contained class can live independently of the first class, outside of its context, or can be shared among other classes. For example, a Department HAS-A Teacher; additionally, every Teacher must belong to Department, but if a Department ceases to exist, a Teacher can still be active as shown in the following diagram:

Composition

As the name suggests, a class is a composition of another one. This is somewhat similar to aggregation, with the difference being that the dependent class ceases to exist when the main class ceases to exist. For example, a House is made up of a Room, but the Room ceases to exist if the House is destroyed, as shown in the following diagram:

In practice, especially in languages such as Java that have garbage collectors, the boundary between composition and aggregation is not so well defined. Objects are not destroyed manually; when they are no longer referenced, they are automatically destroyed by the garbage collector. For this reason, from a coding point of view, we should not really be concerned if we deal with a composition or an aggregation relationship, but it's important if we want to have a well-defined model in UML.