June 4, 2022 • 5 min read
Abstraction design principle

Abstraction is a design principle that emphasizes the creation of abstract representations of complex systems or objects, by hiding their underlying details and exposing only the relevant aspects. The goal of abstraction is to simplify complex systems, making them easier to understand and use.

In software development, abstraction is often achieved through the use of abstract classes, interfaces, or other mechanisms that define a set of common properties or behaviors, while leaving the implementation details to be defined by concrete subclasses or implementations.

The benefits of abstraction in software development include:

  1. Improved maintainability by hiding the implementation details of complex objects or systems, you can make it easier to understand and modify the code, without being bogged down by the details.

  2. Increased reusability by defining abstract objects or systems, you can create reusable components that can be easily adapted to a wide range of different use cases, without having to rewrite the code for each use case.

  3. Improved modularity where abstraction can help you create modular components by defining a clear interface and hiding the implementation details, making it easier to substitute components with other components that provide equivalent functionality.

  4. Improved scalability by creating abstract representations of complex systems, you can make it easier to add or remove features or components as needed, without affecting the rest of the system.

  5. Better collaboration where abstraction can help to create a shared understanding among team members, making it easier for multiple people to work together on a project.

In summary, abstraction is a key design principle that can help you build better, more maintainable, and more scalable software systems. By creating abstract representations of complex objects or systems, you can simplify the code, reduce the risk of bugs, and make it easier to understand, modify, and test the code, while still ensuring that the components work together as a coherent system.

Example

Suppose we want to create a system for processing and storing geometric shapes, such as circles, rectangles, and triangles. We can create an abstract class to represent the common properties of these shapes:

public abstract class Shape {
    private final double area;

    public Shape(double area) {
        this.area = area;
    }

    public double getArea() {
        return area;
    }

    public abstract double getPerimeter();
}

In this example, the Shape class defines the common properties of all shapes, such as the area, and provides an abstract method getPerimeter() that must be implemented by concrete subclasses.

Next, we can create concrete subclasses for each type of shape:

public class Circle extends Shape {
    private final double radius;

    public Circle(double radius) {
        super(Math.PI * radius * radius);
        this.radius = radius;
    }

    @Override
    public double getPerimeter() {
        return 2 * Math.PI * radius;
    }
}

public class Rectangle extends Shape {
    private final double width;
    private final double height;

    public Rectangle(double width, double height) {
        super(width * height);
        this.width = width;
        this.height = height;
    }

    @Override
    public double getPerimeter() {
        return 2 * (width + height);
    }
}

public class Triangle extends Shape {
    private final double base;
    private final double height;

    public Triangle(double base, double height) {
        super(0.5 * base * height);
        this.base = base;
        this.height = height;
    }

    @Override
    public double getPerimeter() {
        // Implementation for calculating the perimeter of a triangle
    }
}

In this example, the Circle, Rectangle, and Triangle classes provide concrete implementations of the Shape class, including the getPerimeter() method.

By using abstraction in this way, we can create a flexible and reusable system for processing and storing geometric shapes. For example, we can easily add new types of shapes by creating additional subclasses of the Shape class, or modify the behavior of existing shapes by modifying the code for the concrete subclasses.

Conclusion

Abstraction makes the code more maintainable, reduces the risk of bugs, and makes it easier to understand, modify, and test the code, while still ensuring that the components work together as a coherent system.

We use cookies to improve your experience. By using our site, you agree to our use of cookies. Read our Privacy Policy for more information.