100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace

What is the Specification Pattern?

The Specification design pattern explained — composable business rules with isSatisfiedBy and and/or/not, with a Java example.

hardQ176 of 226 in Object Oriented Programming Est. time: 6 minsLast updated:
Open Code Lab

Expected Interview Answer

The Specification pattern encapsulates a business rule as a standalone object with an isSatisfiedBy(candidate) method, so rules can be composed with and(), or(), and not() instead of being hard-coded as scattered if-statements.

Each concrete Specification implements a single, named rule (e.g. InStockSpecification, PriceUnderSpecification), which makes the rule reusable, unit-testable in isolation, and self-documenting through its class name rather than buried inside a large conditional. Because specifications expose combinator methods, complex eligibility logic can be built by composing simple specifications: inStock.and(priceUnder(50)).and(not(discontinued)) reads close to the business language it models. This is especially useful for filtering, validation, and selection logic that changes frequently or needs to be expressed identically in multiple contexts (a repository query filter and an in-memory validation check), avoiding duplicated, drifting conditional logic across the codebase.

  • Each business rule becomes a named, independently testable object
  • Rules compose via and/or/not instead of duplicated conditionals
  • The same specification can validate an object or filter a collection/query
  • Reduces duplicated, drifting business logic across the codebase

AI Mentor Explanation

A selection panel doesn’t hard-code “pick players who average over 40 AND have played 20+ matches” as one tangled rule; instead each condition is its own named criterion — an AverageAbove40Spec and a MinimumMatchesSpec — that can be combined for this squad or reused separately for a different tournament’s selection. That is the Specification pattern: each business rule is its own reusable, named object, and complex eligibility is built by composing simple ones with and/or logic rather than one sprawling conditional.

Step-by-Step Explanation

  1. Step 1

    Define the Specification contract

    Create an interface with isSatisfiedBy(candidate) returning a boolean.

  2. Step 2

    Implement individual rules

    Write one small, named class per business rule implementing that interface.

  3. Step 3

    Add combinators

    Implement and(), or(), not() so specifications can be composed into larger rules.

  4. Step 4

    Apply where needed

    Use the same specification object to validate a single instance or filter a collection/query.

What Interviewer Expects

  • Definition centered on isSatisfiedBy() and rule composition via and/or/not
  • Understanding that each rule becomes an independently testable, named object
  • A real example showing reuse of the same specification across contexts
  • Awareness this is a behavioral pattern from Domain-Driven Design, not a GoF pattern

Common Mistakes

  • Confusing it with the Strategy pattern, which selects behavior rather than expressing a composable boolean rule
  • Writing specifications that embed side effects instead of pure boolean evaluation
  • Not implementing the combinators (and/or/not), losing the pattern’s main composability benefit
  • Over-applying it to trivial single-condition checks where a plain boolean method would suffice

Best Answer (HR Friendly)

The Specification pattern turns each business rule into its own small, named object that can answer “does this candidate satisfy me?” These small rule objects can then be combined with and, or, and not to build complex eligibility logic out of simple, reusable, independently testable pieces instead of one big tangled if-statement.

Code Example

Composable Specification pattern
interface Specification<T> {
    boolean isSatisfiedBy(T candidate);

    default Specification<T> and(Specification<T> other) {
        return candidate -> this.isSatisfiedBy(candidate) && other.isSatisfiedBy(candidate);
    }
}

class InStockSpecification implements Specification<Product> {
    public boolean isSatisfiedBy(Product p) { return p.getStock() > 0; }
}

class PriceUnderSpecification implements Specification<Product> {
    private final double limit;
    PriceUnderSpecification(double limit) { this.limit = limit; }
    public boolean isSatisfiedBy(Product p) { return p.getPrice() < limit; }
}

// Usage: compose two independent rules into one eligibility check
Specification<Product> eligible = new InStockSpecification()
        .and(new PriceUnderSpecification(50.0));
boolean canDisplay = eligible.isSatisfiedBy(product);

Follow-up Questions

  • How does the Specification pattern differ from the Strategy pattern?
  • How would you translate a Specification into a database query filter?
  • What is the benefit of unit testing each Specification independently?
  • Where does the Specification pattern originate — is it a GoF pattern?

MCQ Practice

1. The core method every Specification implements is?

isSatisfiedBy(candidate) is the standard method returning whether the candidate meets the encapsulated rule.

2. The main benefit of the Specification pattern over inline conditionals is?

Encapsulating each rule as its own object makes it reusable and testable in isolation rather than buried in a large conditional.

3. Which operations typically let Specifications combine into more complex rules?

and(), or(), and not() combinators let simple specifications compose into complex business rules.

Flash Cards

Specification pattern in one line?Encapsulate a business rule as an object with isSatisfiedBy(candidate).

How are rules combined?Via and(), or(), and not() combinator methods.

Main benefit?Each rule is a small, named, independently reusable and testable object.

Common confusion?Strategy pattern selects behavior; Specification evaluates a composable boolean rule.

1 / 4

Continue Learning