Spec<T> class
sealed
The Specification Pattern: compose business rules as reusable, testable predicates.
A Spec represents a single business rule that an object either satisfies or doesn't. Instead of embedding validation logic directly in methods, specifications are first-class objects that can be created, combined, tested, and reused independently.
This pattern is ideal for:
- Domain rules: Entity validation, filtering, and search criteria
- Reusability: The same rule applies in multiple contexts without duplication
- Testability: Each rule is isolated and easy to unit test
- Composability: Combine simple rules into complex business logic
- Readability: Express business intent clearly through method names
Compose specs using:
&/ and — Both must be satisfied (AND logic)|/ or — At least one must be satisfied (OR logic)^/ xor — Exactly one must be satisfied, not both (XOR logic)- toNegated — Inverts the rule (NOT logic)
Creating a Spec:
/// Business rule: person is old enough to vote
class IsEligibleVoter extends Spec<Person> {
@override
bool isSatisfiedBy(Person person) => person.age >= 18;
}
/// Business rule: person has valid contact info
class HasValidEmail extends Spec<Person> {
@override
bool isSatisfiedBy(Person person) => person.email.contains('@');
}
Using a Spec:
// Single rule
final isVoter = IsEligibleVoter();
if (isVoter.isSatisfiedBy(person)) {
registerToVote(person);
}
// Composed rules
final validVoter = IsEligibleVoter() & HasValidEmail();
final voters = people.where((p) => validVoter.isSatisfiedBy(p)).toList();
// Complex compositions
final canReceiveNewsletter = HasValidEmail() & (IsEligibleVoter() | HasOptedIn());
- Annotations
-
- @experimental
Properties
- hashCode → int
-
The hash code for this object.
no setterinherited
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
Methods
-
and(
Spec< T> other) → Spec<T> - Combines this spec with another using AND logic.
-
isSatisfiedBy(
T candidate) → bool -
Checks if
candidatesatisfies this specification. -
nand(
Spec< T> other) → Spec<T> - Combines this spec with another using NAND logic (NOT AND).
-
nor(
Spec< T> other) → Spec<T> - Combines this spec with another using NOR logic (NOT OR).
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
or(
Spec< T> other) → Spec<T> - Combines this spec with another using OR logic.
-
toNegated(
) → Spec< T> - Creates a new spec that is the logical negation of this spec.
-
toString(
) → String -
A string representation of this object.
inherited
-
xnor(
Spec< T> other) → Spec<T> - Combines this spec with another using XNOR logic (NOT XOR / equivalence).
-
xor(
Spec< T> other) → Spec<T> - Combines this spec with another using XOR logic (exclusive OR).
Operators
-
operator &(
Spec< T> other) → Spec<T> - Combines this spec with another using AND logic (&).
-
operator ==(
Object other) → bool -
The equality operator.
inherited
-
operator ^(
Spec< T> other) → Spec<T> - Combines this spec with another using XOR logic (^).
-
operator |(
Spec< T> other) → Spec<T> - Combines this spec with another using OR logic (|).