When Should You Use Abstract Classes in Java? Avoid the Swiss‑Army‑Knife Controller Anti‑Pattern

This article explains the purpose and proper use of abstract classes in Java, illustrates common misuse such as the Swiss‑Army‑Knife controller anti‑pattern, and demonstrates how the Template Method pattern can provide a cleaner design with concrete examples and code snippets.

Programmer DD
Programmer DD
Programmer DD
When Should You Use Abstract Classes in Java? Avoid the Swiss‑Army‑Knife Controller Anti‑Pattern

Definition of Abstract Classes

Technically, an abstract class is a class that cannot be instantiated directly and is intended to be extended by concrete subclasses. It may define one or more abstract methods without bodies, which concrete subclasses must implement.

Simple Example

public abstract class Base {
    public void doSomething() {
        System.out.println("Doing something...");
    }
    public abstract void doSomethingElse();
}

Attempting to instantiate Base results in a compilation error:

Base b = new Base(); // error: Base is abstract and cannot be instantiated

Instead, create a concrete subclass:

public class Sub extends Base {
    @Override
    public void doSomethingElse() {
        System.out.println("Doin' something else!");
    }
}

Swiss‑Army‑Knife Controller Anti‑Pattern

Developers often over‑use abstract base controllers in MVC frameworks, adding many shared utility methods to a single BaseController. Subclasses inherit all these methods, even when they are unrelated, leading to a bloated hierarchy and unnecessary dependencies.

Problems include:

Design issue: unrelated controllers are forced into a common inheritance tree.

Practical issue: code in other layers must instantiate a controller just to reuse a utility method, creating tight coupling and making testing harder.

Instead, move shared functionality to dedicated service or utility classes that can be instantiated independently.

Template Method Pattern

The Template Method pattern defines the skeleton of an algorithm in an abstract class, delegating specific steps to subclasses. This avoids the Swiss‑Army‑Knife anti‑pattern by keeping shared workflow in the base class and allowing subclasses to customize only the variable parts.

public abstract class BaseUserController {
    @POST
    @Path("/user")
    public UserDto createUser(UserInfo userInfo) {
        UserDto u = userMapper.map(userInfo);
        u.setCreatedDate(Instant.now());
        u.setValidationCode(validationUtil.generatedCode());
        setRoles(u); // implemented by subclasses
        userDao.save(u);
        mailerUtil.sendInitialEmail(u);
        return u;
    }
    protected abstract void setRoles(UserDto u);
}

Concrete subclasses implement the abstract setRoles method:

@Path("employee")
public class EmployeeUserController extends BaseUserController {
    @Override
    protected void setRoles(UserDto u) {
        u.addRole(Role.employee);
    }
}

@Path("admin")
public class AdminUserController extends BaseUserController {
    @Override
    protected void setRoles(UserDto u) {
        u.addRole(Role.admin);
        if (u.hasSuperUserAccess()) {
            u.addRole(Role.superUser);
        }
    }
}

When a new user type is needed, simply create a new subclass and implement setRoles, keeping the common workflow unchanged.

Rule of Thumb

Ask yourself whether callers invoke methods implemented in the abstract base class or in concrete subclasses. If most calls target base‑class implementations, the abstraction is likely appropriate; if callers mainly use subclass‑specific behavior, you may be creating a Swiss‑Army‑Knife anti‑pattern.

Original article: https://dzone.com/articles/when-to-use-java-abstract-classes Author: Dave Taubler Translator: xuli
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Design PatternsJavaMVCBackend DevelopmentAbstract Classes
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.