# How DDDplus Implements the Specification Pattern with AndSpecification and OrSpecification

> Discover how DDDplus implements the Specification pattern using AndSpecification and OrSpecification. Learn to create composable business rules with logical conjunction and disjunction.

- Repository: [Funky Gao/cp-ddd-framework](https://github.com/funkygao/cp-ddd-framework)
- Tags: deep-dive
- Published: 2026-03-02

---

**DDDplus implements the Specification pattern through a composable hierarchy where `AbstractSpecification` provides `and()` and `or()` methods that return `AndSpecification` and `OrSpecification` instances, enabling logical conjunction and disjunction of business rules.**

The `funkygao/cp-ddd-framework` (DDDplus) provides a clean, extensible implementation of the Specification pattern that allows domain developers to encapsulate business rules as discrete, reusable objects. By leveraging `AndSpecification` for logical AND operations and `OrSpecification` for logical OR operations, DDDplus enables complex validation logic to be built through method chaining while maintaining clean separation of concerns.

## Core Components of the DDDplus Specification Pattern

### ISpecification Interface

The foundation of the pattern is the `ISpecification<T>` interface located in [`dddplus-spec/src/main/java/io/github/dddplus/model/spcification/ISpecification.java`](https://github.com/funkygao/cp-ddd-framework/blob/main/dddplus-spec/src/main/java/io/github/dddplus/model/spcification/ISpecification.java). This contract defines two overloaded methods for evaluating whether a candidate object satisfies the specification:

```java
public interface ISpecification<T> {
    boolean isSatisfiedBy(T candidate);
    boolean isSatisfiedBy(T candidate, Notification notification);
}

```

The second method accepts a `Notification` object that aggregates validation errors, allowing specifications to collect multiple failure reasons without throwing exceptions immediately.

### AbstractSpecification Base Class

The `AbstractSpecification<T>` class in [`dddplus-spec/src/main/java/io/github/dddplus/model/spcification/AbstractSpecification.java`](https://github.com/funkygao/cp-ddd-framework/blob/main/dddplus-spec/src/main/java/io/github/dddplus/model/spcification/AbstractSpecification.java) provides the compositional infrastructure. It implements the basic `isSatisfiedBy(T candidate)` by delegating to the notification-aware version, and crucially, it defines the `and()` and `or()` factory methods:

```java
public abstract class AbstractSpecification<T> implements ISpecification<T> {
    @Override
    public final boolean isSatisfiedBy(T candidate) {
        return isSatisfiedBy(candidate, Notification.build());
    }

    public AbstractSpecification<T> and(final ISpecification<T> specification) {
        return new AndSpecification<T>(this, specification);
    }

    public AbstractSpecification<T> or(final ISpecification<T> specification) {
        return new OrSpecification<T>(this, specification);
    }
}

```

These methods enable fluent chaining, allowing developers to compose complex logical expressions from simple specifications.

## How AndSpecification Implements Logical AND

The `AndSpecification<T>` class in [`dddplus-spec/src/main/java/io/github/dddplus/model/spcification/AndSpecification.java`](https://github.com/funkygao/cp-ddd-framework/blob/main/dddplus-spec/src/main/java/io/github/dddplus/model/spcification/AndSpecification.java) implements logical conjunction. It stores references to two inner specifications—`left` and `right`—and evaluates both when checking satisfaction:

```java
public class AndSpecification<T> extends AbstractSpecification<T> {
    private ISpecification<T> left;
    private ISpecification<T> right;

    public AndSpecification(final ISpecification<T> left,
                            final ISpecification<T> right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public boolean isSatisfiedBy(T candidate, Notification notification) {
        return left.isSatisfiedBy(candidate, notification) &&
               right.isSatisfiedBy(candidate, notification);
    }
}

```

The implementation uses short-circuit evaluation naturally through the `&&` operator. If the `left` specification fails, the `right` specification is still evaluated (to collect all errors in the `Notification`), but the final result will be false.

## How OrSpecification Implements Logical OR

The `OrSpecification<T>` class in [`dddplus-spec/src/main/java/io/github/dddplus/model/spcification/OrSpecification.java`](https://github.com/funkygao/cp-ddd-framework/blob/main/dddplus-spec/src/main/java/io/github/dddplus/model/spcification/OrSpecification.java) provides logical disjunction. Similar to `AndSpecification`, it wraps two specifications but uses the `||` operator to determine satisfaction:

```java
public class OrSpecification<T> extends AbstractSpecification<T> {
    private ISpecification<T> left;
    private ISpecification<T> right;

    public OrSpecification(final ISpecification<T> left,
                           final ISpecification<T> right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public boolean isSatisfiedBy(T candidate, Notification notification) {
        return left.isSatisfiedBy(candidate, notification) ||
               right.isSatisfiedBy(candidate, notification);
    }
}

```

This implementation satisfies the specification if either the `left` or `right` rule passes. Note that due to short-circuiting with `||`, if the `left` specification succeeds, the `right` specification is not evaluated.

## Notification and Error Aggregation

Both `AndSpecification` and `OrSpecification` rely on the `Notification` class located in [`dddplus-spec/src/main/java/io/github/dddplus/model/spcification/Notification.java`](https://github.com/funkygao/cp-ddd-framework/blob/main/dddplus-spec/src/main/java/io/github/dddplus/model/spcification/Notification.java) to collect validation errors. Rather than throwing exceptions immediately, specifications add error messages to the `Notification` instance, allowing composite specifications to accumulate multiple failure reasons across `and()` and `or()` chains.

## Practical Usage Examples

### Creating a Concrete Specification

Domain developers extend `AbstractSpecification` to implement specific business rules:

```java
class IntegerGreaterThanSpec extends AbstractSpecification<Integer> {
    private final int threshold;
    
    IntegerGreaterThanSpec(int threshold) { 
        this.threshold = threshold; 
    }

    @Override
    public boolean isSatisfiedBy(Integer candidate, Notification notification) {
        if (candidate <= threshold) {
            notification.addError(
                String.format("candidate:%d is not more than %d", candidate, threshold));
            return false;
        }
        return true;
    }
}

```

### Chaining with AndSpecification

Combine multiple specifications using the `and()` method to create an `AndSpecification`:

```java
ISpecification<Integer> spec = new IntegerGreaterThanSpec(1)
        .and(new IntegerGreaterThanSpec(2))
        .and(new IntegerGreaterThanSpec(3));

boolean ok = spec.isSatisfiedBy(4);                // true
Notification note = Notification.build();
boolean fails = spec.isSatisfiedBy(2, note);       // false
System.out.println(note.first());                  // "candidate:2 is not more than 3"

```

### Chaining with OrSpecification

Use the `or()` method to create an `OrSpecification` for alternative validation paths:

```java
ISpecification<Integer> spec = new IntegerGreaterThanSpec(1)
        .or(new IntegerGreaterThanSpec(2))
        .or(new IntegerGreaterThanSpec(3));

assert spec.isSatisfiedBy(2);   // true – the second spec passes
assert !spec.isSatisfiedBy(1); // false – none of the specs pass (wait, actually 1 > 1 is false, 1 > 2 is false, 1 > 3 is false) - correct

```

### Integration in Domain Services

Specifications integrate cleanly with domain services for validation:

```java
public class OrderService {
    private final ISpecification<Order> orderValidSpec;

    public OrderService(ISpecification<Order> orderValidSpec) {
        this.orderValidSpec = orderValidSpec;
    }

    public void place(Order order) {
        Notification note = Notification.build();
        if (!orderValidSpec.isSatisfiedBy(order, note)) {
            throw new IllegalArgumentException("Order validation failed: " + note.first());
        }
        // proceed with business logic…
    }
}

```

## Summary

- **DDDplus** implements the Specification pattern through the `ISpecification<T>` interface and `AbstractSpecification<T>` base class in the `dddplus-spec` module.
- **`AndSpecification`** combines two specifications with logical AND, requiring both `left` and `right` specifications to pass.
- **`OrSpecification`** combines two specifications with logical OR, requiring either `left` or `right` to pass.
- Both composite specifications use the `Notification` class to aggregate validation errors without throwing immediate exceptions.
- Method chaining via `and()` and `or()` enables fluent construction of complex validation rules from simple, reusable specifications.

## Frequently Asked Questions

### What is the Specification pattern in DDDplus?

The Specification pattern in DDDplus is a design pattern used to encapsulate business rules as discrete, reusable objects. Implemented in the `dddplus-spec` module, it allows domain developers to define validation logic that can be combined using `AndSpecification` and `OrSpecification` to form complex rules without duplicating code or creating deep inheritance hierarchies.

### How does AndSpecification differ from OrSpecification in DDDplus?

`AndSpecification` requires both the left and right specifications to return true for the composite to pass, implementing logical conjunction. In contrast, `OrSpecification` passes if either the left or right specification returns true, implementing logical disjunction. Both classes extend `AbstractSpecification` and are instantiated through the `and()` and `or()` factory methods respectively.

### Can I chain multiple AndSpecification and OrSpecification calls?

Yes, DDDplus supports fluent chaining of specifications. Since both `and()` and `or()` return `AbstractSpecification<T>`, you can chain multiple calls to build complex logical expressions. For example, `spec1.and(spec2).or(spec3).and(spec4)` creates a composite specification that evaluates according to the rules of operator precedence and short-circuit evaluation.

### How does DDDplus handle errors when specifications fail?

Rather than throwing exceptions immediately, DDDplus uses a `Notification` object passed to `isSatisfiedBy(candidate, notification)`. When a specification fails, it adds error messages to this notification. For composite specifications like `AndSpecification` and `OrSpecification`, the same notification instance is passed to child specifications, allowing aggregation of all validation errors across the entire specification chain.