Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Practical Design Patterns for Java Developers

You're reading from   Practical Design Patterns for Java Developers Hone your software design skills by implementing popular design patterns in Java

Arrow left icon
Product type Paperback
Published in Feb 2023
Publisher Packt
ISBN-13 9781804614679
Length 266 pages
Edition 1st Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Miroslav Wengner Miroslav Wengner
Author Profile Icon Miroslav Wengner
Miroslav Wengner
Arrow right icon
View More author details
Toc

Table of Contents (14) Chapters Close

Preface 1. Part 1: Design Patterns and Java Platform Functionalities
2. Chapter 1: Getting into Software Design Patterns FREE CHAPTER 3. Chapter 2: Discovering the Java Platform for Design Patterns 4. Part 2: Implementing Standard Design Patterns Using Java Programming
5. Chapter 3: Working with Creational Design Patterns 6. Chapter 4: Applying Structural Design Patterns 7. Chapter 5: Behavioral Design Patterns 8. Part 3: Other Essential Patterns and Anti-Patterns
9. Chapter 6: Concurrency Design Patterns 10. Chapter 7: Understanding Common Anti-Patterns 11. Assessments 12. Index 13. Other Books You May Enjoy

Examining OOP and APIE

In the previous section, we learned how a program written in one of the high-level languages is converted into machine instructions that are processed by the CPU. The high-level language provides a framework for expressing the desired ideas by following the details of the language implementation. Such languages commonly provide many neat constructions or statements that do not limit the imagination. In object-oriented programming (OOP) language, the representation of the core carrier is presented by the concept of the object. This book focuses on the Java language. Java is a fully object-oriented language with additional features. What does object-oriented language mean exactly? In computer science, this means that the program focuses on the concept of classes, where instances of these classes represent an object. Next, we will repeat the importance of the OOP paradigm and deal with some basic concepts.

These terms can be expressed by the abbreviation of abstraction, polymorphism, inheritance, and encapsulation (APIE). The letters APIE indicate the four basic pillars of OOP languages. Let’s examine each word in a separate section in reverse order – so, EIPA. The motivation is to bring more clarity to our understanding of the concept of OOP.

Only exposing what’s required – encapsulation

The first in reverse order is encapsulation – let’s start with it. OOP languages, including Java, work with the concept of classes. Imagine that a class is a vehicle. The class provides all the fields that can be statically typed or object-specific – that is, initiated after an object is instantiated in the allocated memory. The concept is similar with respect to class or object methods. The method may belong to a class or its instance – in the considered example, to a vehicle. Any method can work over an object or class field and change the internal state of the vehicle or the field values (see Example 1.1):

public class Vehicle {
    private boolean moving;
    public void move(){
        this.moving = true;
        System.out.println("moving...");
    }
    public void stop(){
        this.moving = false;
        System.out.println("stopped...");
    }
}

We can apply encapsulation to the example of a vehicle. We imagine a real vehicle – only one. In such an imaginary vehicle, all internal elements and internal functions remain hidden from the driver. It only exposes the functionality it serves, such as the steering wheel, which the driver can control. This is the general principle of encapsulation. The state of an instance can be changed or updated through exposed methods or fields; everything else is hidden from the outside world. It is quite a good practice to use methods to modify the inner array or arrays of an instance. But we will repeat that later in this book. So far, it’s just a good hint.

Inevitable evolution – inheritance

In the previous section, an instance of an imaginary vehicle class was created. We encapsulated all the functions that should not be exposed to the driver. This means that the driver may not know how the engine works, only how to use it.

This section is devoted to the property of inheritance, which we will demonstrate in the following example. Assume that the vehicle’s engine is broken. How can we replace it? The goal is to replace the current one with a functional one. An engine that works this way may not necessarily be the same, especially if the vehicle model already has old parts that are not available on the market.

What we do is derived from all the attributes and functions needed to create a new engine. Concerning the class, the new replacement module will be a child in the class hierarchy.

Although the engine will not be a perfect replica and does not have the same unique object identifier, it will match all the parent properties.

With that, we have described the second pillar of inheritance in OOP – the ability to create a new class above the existing subclass. However, software designers should be wary of the fourth pillar, encapsulation, and any violations caused by a subclass depending on the implementation details of its superclass.

Behavior on demand – polymorphism

The third concept is polymorphism. With a little imagination, this can be understood as “many forms.” So, what does that mean here?

Given the vehicle described previously, it could be defined as the ability to perform a particular action in many ways. This would mean, in the context of a vehicle, that the movement of the other method, move, could happen differently based on the inputs or the state of the instance.

Java allows for two types of polymorphism, both of which differ in their runtime behavior. We will discuss both in detail.

Method overloading

This type is known as static polymorphism. This means that the correct method is resolved during program compilation – so, at compile time. Java provides two types of method overloads:

  • Changing the input argument type:
Figure 1.4 – Overloading the method of the Vehicle class by changing the input types

Figure 1.4 – Overloading the method of the Vehicle class by changing the input types

  • Changing the number of method arguments:
Figure 1.5 – Overloading the method of the Vehicle class by changing the number of arguments

Figure 1.5 – Overloading the method of the Vehicle class by changing the number of arguments

Now, let’s look at the second type of polymorphism.

Method overriding

This is sometimes called dynamic polymorphism. This means that the method performed is known at runtime. The overridden method is called through reference to the object instance of belongingness. Let us examine a simple example to illustrate this. Consider the Vehicle class a parent class (see Figure 1.6 and Example 1.2) with a method called move:

Figure 1.6 – The relation between the overridden move methods for the parent and child classes

Figure 1.6 – The relation between the overridden move methods for the parent and child classes

We intend to create a child class, Car, with a similar method named move. The child provides slightly different functions because the Car instance moves faster than the parent instance, Vehicle:

public class Vehicle {
    public void move(){
        System.out.println("moving...");
    }
}
public class Car extends Vehicle {
    @Override
    public void move(){
        System.out.println("moving faster.");
    }
}
Vehicle vehicle = new Car();
vehicle.move();
output: moving faster...

We will touch on this topic in more detail in Chapter 3, Working with Creational Design Patterns.

Standard features – abstraction

The last letter to cover (but the first letter in the abbreviation APIE) leads us to the hitherto unspecified pillar of abstraction. The key to this concept is the constant removal of specifics or individual details to achieve the generalization of the purpose of the object.

To get the best experience with this concept, let us get into the context with the vehicle example. We do not intend to describe a specific car model that belongs to a group of vehicles. Our goal is to define a common functionality that all types of vehicles under consideration can include in the context of our efforts. With such knowledge, we create a suitable abstraction, an abstract class that can be inherited later when constructing a particular model class (see Example 1.3).

This approach allows us to focus our efforts on generalizing and abstracting vehicle characteristics. This can have a positive impact on code reduction and reusability.

The abstraction in Java can be achieved in two ways:

  • Abstract classes with abstract methods (see Example 1.3 and Figure 1.7):
Figure 1.7 – The AbstractVehicle class with its CommonCar realizations and SportCar classes

Figure 1.7 – The AbstractVehicle class with its CommonCar realizations and SportCar classes

public abstract class AbstractVehicle {
    abstract public void move();
    public void stop(){
        System.out.println("stopped...");
    }
}
public class CommonCar extends AbstractVehicle{
    @Override
    public void move() {
        System.out.println("move slow...");
    }
}
public class SportCar extends AbstractVehicle{
    @Override
    public void move() {
        System.out.println("move fast...");
    }
}
  • Using interfaces (see Example 1.4 and Figure 1.8) with a generic abstract method:
Figure 1.8 – The abstraction concept achieved by using interfaces

Figure 1.8 – The abstraction concept achieved by using interfaces

public interface VehicleInterface {
    void move();
}
public class Truck implements VehicleInterface{
    @Override
    public void move() {
        System.out.println("truck moves...");
    }
}
public class Bus implements VehicleInterface{
    @Override
    public void move() {
        System.out.println("bus moves...");
    }
}

Both concepts of abstraction can be combined (see Figure 1.9):

Figure 1.9 – A combination of both abstraction concepts

Figure 1.9 – A combination of both abstraction concepts

Abstract classes and interfaces have their place in the design of code structure. Their use depends on demand, but both have a very positive impact on code maintainability and help in the use of design patterns.

Gluing parts to APIE

The motivation for each of the pillars mentioned in the previous sections is to introduce structure into the code through a given set of concepts. The pillars are defined and complementary. Let’s just examine one unit, the Vehicle class, and its instance. Instance logic and data are encapsulated and exposed through methods to the outside world. Vehicle characteristics can be inherited so that a new vehicle design, such as a new model, can be specified. Exposed methods can provide model-based behavior and incoming arguments with internal instance state changes. When crystalizing thoughts about a new vehicle, we can always generalize its behavior and extract it using an abstract class or interface.

Let us examine the generalization process over the Vehicle class development. When preparing to define a new vehicle model, we can always generalize its characteristics and extract it using an abstract class or interface. Let’s look at the following diagram:

Figure 1.10 – APIE viewed as a continual improvement process

Figure 1.10 – APIE viewed as a continual improvement process

Although these four pillars seem trivial, it is incredibly difficult to follow them, as we will continue to show in the following sections and chapters.

So far in this section, we learned about the four basic pillars of OOP and examined how these principles affect code design. Next, we will learn more about sustainable code design concepts. Let us roll on to the following section.

You have been reading a chapter from
Practical Design Patterns for Java Developers
Published in: Feb 2023
Publisher: Packt
ISBN-13: 9781804614679
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime