Specifications allow simple classes to encapsulate business rules in a flexible, testable, and reusable manner.
import 'package:specify/specify.dart'; class StringContains extends Specification<String> { final String _substring; StringContains(this._substring); bool isSatisfiedBy(String aString) => aString.contains(_substring); } class StringNotContains extends StringContains { StringNotContains(String aSubstring) : super(aSubstring); bool isSatisfiedBy(String aString) => !super.isSatisfiedBy(aString); } class StringIn extends OrSpecification<String> { StringIn(List<String> aWordList) : super( aWordList.map((String aWord) => new StringContains(aWord)).toList() ); } class StringNotIn extends AndSpecification<String> { StringNotIn(List<String> aWordList) : super( aWordList.map((String aWord) => new StringNotContains(aWord)).toList() ); } main() { StringIn isWord = new StringIn(['foo', 'bar']); StringNotIn isNotWord = new StringNotIn(['baz', 'zim']); print(isWord('barge')); print(isNotWord('hello')); }
Filtering with specifications can be very powerful, especially when used with CompositeSpecification.
import 'package:specify/specify.dart'; class StringLength extends Specification<String> { final int _length; StringLength(this._length); bool isSatisfiedBy(String aString) => aString.length == _length; } class LengthFilter extends Filter<String> { LengthFilter(int aLength) : super(new StringLength(aLength)); } main() { LengthFilter filter = new LengthFilter(3); print(filter(['foo', 'bar', 'nice', 'to', 'know', 'you'])); }