Specification pattern: Difference between revisions

Content deleted Content added
No edit summary
Rdckc (talk | contribs)
m corrected compilation error
 
(3 intermediate revisions by 3 users not shown)
Line 1:
{{shortShort description|Software design pattern}}
[[ImageFile:Specification UML.png|right|thumb|300px|Specification Pattern in [[Unified Modeling Language|UML]] ]]
In computer programming, the '''specification pattern''' is a particular [[software design pattern]], whereby [[business rules]] can be recombined by chaining the business rules together using [[boolean algebra|boolean logic]]. The pattern is frequently used in the context of [[___domain-driven design]].
 
A specification pattern outlines a business rule that is combinable with other business rules. In this pattern, a unit of business logic inherits its functionality from the abstract aggregate Composite Specification class. The Composite Specification class has one function called IsSatisfiedBy that returns a boolean value. After instantiation, the specification is "chained" with other specifications, making new specifications easily maintainable, yet highly customizable business logic. Furthermore, upon instantiation the business logic may, through method invocation or [[inversion of control]], have its state altered in order to become a delegate of other classes such as a persistence repository.
 
As a consequence of performing runtime composition of high-level business/___domain logic, the Specification pattern is a convenient tool for converting ad-hoc user search criteria into low level logic to be processed by repositories.
Line 11:
== Code examples ==
 
=== [[C Sharp (programming language)|C#]] ===
{{Further|C Sharp (programming language)}}
 
<syntaxhighlight lang="csharp">
public interface ISpecification
Line 56:
public class AndSpecification : CompositeSpecification
{
private ISpecification leftCondition_leftCondition;
private ISpecification rightCondition_rightCondition;
 
public AndSpecification(ISpecification left, ISpecification right)
{
leftCondition_leftCondition = left;
rightCondition_rightCondition = right;
}
 
public override bool IsSatisfiedBy(object candidate)
{
return leftCondition_leftCondition.IsSatisfiedBy(candidate) && rightCondition_rightCondition.IsSatisfiedBy(candidate);
}
}
Line 73:
public class AndNotSpecification : CompositeSpecification
{
private ISpecification leftCondition_leftCondition;
private ISpecification rightCondition_rightCondition;
 
public AndNotSpecification(ISpecification left, ISpecification right)
{
leftCondition_leftCondition = left;
rightCondition_rightCondition = right;
}
 
public override bool IsSatisfiedBy(object candidate)
{
return leftCondition_leftCondition.IsSatisfiedBy(candidate) && rightCondition_rightCondition.IsSatisfiedBy(candidate) != true;
}
}
Line 90:
public class OrSpecification : CompositeSpecification
{
private ISpecification leftCondition_leftCondition;
private ISpecification rightCondition_rightCondition;
 
public OrSpecification(ISpecification left, ISpecification right)
{
leftCondition_leftCondition = left;
rightCondition_rightCondition = right;
}
 
public override bool IsSatisfiedBy(object candidate)
{
return leftCondition_leftCondition.IsSatisfiedBy(candidate) || rightCondition_rightCondition.IsSatisfiedBy(candidate);
}
}
Line 107:
public class OrNotSpecification : CompositeSpecification
{
private ISpecification leftCondition_leftCondition;
private ISpecification rightCondition_rightCondition;
 
public OrNotSpecification(ISpecification left, ISpecification right)
{
leftCondition_leftCondition = left;
rightCondition_rightCondition = right;
}
 
public override bool IsSatisfiedBy(object candidate)
{
return leftCondition_leftCondition.IsSatisfiedBy(candidate) || rightCondition_rightCondition.IsSatisfiedBy(candidate) != true;
}
}
Line 124:
public class NotSpecification : CompositeSpecification
{
private ISpecification Wrapped_wrapped;
 
public NotSpecification(ISpecification x)
{
Wrapped_wrapped = x;
}
 
public override bool IsSatisfiedBy(object candidate)
{
return !Wrapped_wrapped.IsSatisfiedBy(candidate);
}
}
</syntaxhighlight>
 
=== [[C Sharp (programming language)|C# 6.0]] with generics ===
{{Further|C Sharp (programming language)}}
 
<syntaxhighlight lang="csharp">
public interface ISpecification<T>
Line 169:
public class AndSpecification<T> : CompositeSpecification<T>
{
private ISpecification<T> left_left;
private ISpecification<T> right_right;
 
public AndSpecification(ISpecification<T> left, ISpecification<T> right)
{
this.left_left = left;
this.right_right = right;
}
 
public override bool IsSatisfiedBy(T candidate) => left_left.IsSatisfiedBy(candidate) && right_right.IsSatisfiedBy(candidate);
}
 
public class AndNotSpecification<T> : CompositeSpecification<T>
{
private ISpecification<T> left_left;
private ISpecification<T> right_right;
 
public AndNotSpecification(ISpecification<T> left, ISpecification<T> right)
{
this.left_left = left;
this.right_right = right;
}
 
public override bool IsSatisfiedBy(T candidate) => left_left.IsSatisfiedBy(candidate) && !right_right.IsSatisfiedBy(candidate);
}
 
public class OrSpecification<T> : CompositeSpecification<T>
{
private ISpecification<T> left_left;
private ISpecification<T> right_right;
 
public OrSpecification(ISpecification<T> left, ISpecification<T> right)
{
this.left_left = left;
this.right_right = right;
}
 
public override bool IsSatisfiedBy(T candidate) => left_left.IsSatisfiedBy(candidate) || right_right.IsSatisfiedBy(candidate);
}
public class OrNotSpecification<T> : CompositeSpecification<T>
{
private ISpecification<T> left_left;
private ISpecification<T> right_right;
 
public OrNotSpecification(ISpecification<T> left, ISpecification<T> right)
{
this.left_left = left;
this.right_right = right;
}
 
public override bool IsSatisfiedBy(T candidate) => left_left.IsSatisfiedBy(candidate) || !right_right.IsSatisfiedBy(candidate);
}
 
Line 230:
</syntaxhighlight>
 
=== [[Python (programming language)|Python]] ===
{{Further|Python (programming language)}}
<syntaxhighlight lang="python">
from abc import ABC, abstractmethod
Line 278 ⟶ 279:
</syntaxhighlight>
 
=== [[C++ (programming language)|C++]] ===
{{Further|C++}}
<syntaxhighlight lang="cpp">
template <class T>
Line 421 ⟶ 423:
</syntaxhighlight>
 
=== [[TypeScript]] ===
{{Further|TypeScript}}
 
<syntaxhighlight lang="typescript">
export interface ISpecification {
Line 510 ⟶ 512:
==Example of use==
 
In the followingnext example, weinvoices are retrieving invoicesretrieved and sending themsent to a collection agency if:
 
# they are overdue,
Line 516 ⟶ 518:
# they are not already with the collection agency.
 
This example is meant to show the end result of how the logic is 'chained' together.
 
This usage example assumes a previously defined <code>OverdueSpecification</code> class that is satisfied when an invoice's due date is 30 days or older, a <code>NoticeSentSpecification</code> class that is satisfied when three notices have been sent to the customer, and an <code>InCollectionSpecification</code> class that is satisfied when an invoice has already been sent to the collection agency. The implementation of these classes isn't important here.
 
Using these three specifications, we created a new specification called <code>SendToCollection</code> which will be satisfied when an invoice is overdue, when notices have been sent to the customer, and are not already with the collection agency.
 
<syntaxhighlight lang="csharp">
var overDueoverdue = new OverDueSpecificationOverdueSpecification();
var noticeSent = new NoticeSentSpecification();
var inCollection = new InCollectionSpecification();
 
// Example of specification pattern logic chaining
var sendToCollection = overDueoverdue.And(noticeSent).And(inCollection.Not());
 
var invoiceCollectioninvoices = ServiceInvoiceService.GetInvoices();
 
foreach (var currentInvoiceinvoice in invoiceCollectioninvoices)
{
if (sendToCollection.IsSatisfiedBy(currentInvoiceinvoice))
{
currentInvoiceinvoice.SendToCollection();
}
}
Line 554 ⟶ 556:
* [https://web.archive.org/web/20110724151447/http://www.dpdk.nl/opensource/specification-pattern-for-selection-on-lists specification pattern in flash actionscript 3] by Rolf Vreijdenberger
 
{{Design Patterns Patternspatterns}}
 
[[Category:Architectural pattern (computer science)]]
[[Category:Articles with example C Sharp code]]
[[Category:Software design patterns]]
[[Category:Programming language comparisons]]
<!-- Hidden categories below -->
[[Category:Articles with example C Sharp code]]
[[Category:Articles with example C++ code]]
[[Category:Articles with example JavaScript code]]
[[Category:Articles with example Python (programming language) code]]