В компьютерном программировании шаблон спецификации - это особый шаблон проектирования программного обеспечения , посредством которого бизнес-правила могут быть рекомбинированы путем объединения бизнес-правил вместе с использованием логической логики. Шаблон часто используется в контексте проектирования, ориентированного на предметную область .
Шаблон спецификации описывает бизнес-правило, которое можно комбинировать с другими бизнес-правилами. В этом шаблоне единица бизнес-логики наследует свои функции от абстрактного совокупного класса составной спецификации. В классе Composite Specification есть одна функция IsSatisfiedBy, которая возвращает логическое значение. После инстанцирования спецификация «связывается» с другими спецификациями, что делает новые спецификации легко обслуживаемыми, но при этом легко настраиваемой бизнес-логикой. Кроме того, при создании экземпляра бизнес-логика может, посредством вызова метода или инверсии управления , изменить свое состояние, чтобы стать делегатом других классов, таких как репозиторий постоянства.
Как следствие выполнения компоновки высокоуровневой бизнес-логики / предметной логики во время выполнения, шаблон спецификации представляет собой удобный инструмент для преобразования специальных критериев поиска пользователей в низкоуровневую логику, которая будет обрабатываться репозиториями.
Примеры кода [ править ]
C # [ править ]
открытый интерфейс ISpecification { bool IsSatisfiedBy ( объект- кандидат ); ISpecification А ( ISpecification другое ); ISpecification AndNot ( ISpecification другое ); ISpecification или ( ISpecification другое ); IS спецификация OrNot ( другая спецификация IS ); ISpecification Not (); } общедоступный абстрактный класс CompositeSpecification : ISpecification { общедоступный абстрактный логический объект IsSatisfiedBy ( объект- кандидат ); public ISpecification And ( ISpecification other ) { вернуть новую AndSpecification ( это , другое ); } public ISpecification AndNot ( ISpecification other ) { вернуть новую AndNotSpecification ( это , другое ); } public ISpecification Or ( ISpecification other ) { return new OrSpecification ( this , other ); } public ISpecification OrNot ( ISpecification other ) { вернуть новую спецификацию OrNot ( это , другое ); } public ISpecification Not () { вернуть новую NotSpecification ( это ); } } открытый класс AndSpecification : CompositeSpecification { частная ISpecification leftCondition ; private ISpecification rightCondition ; общедоступная AndSpecification ( ISpecification слева , ISpecification справа ) { leftCondition = left ; rightCondition = право ; } public override bool IsSatisfiedBy ( объект- кандидат ) { return leftCondition . IsSatisfiedBy ( кандидат ) && rightCondition . IsSatisfiedBy ( кандидат ); } } открытый класс AndNotSpecification : CompositeSpecification { частная ISpecification leftCondition ; private ISpecification rightCondition ; общедоступная AndNotSpecification ( ISpecification слева , ISpecification справа ) { leftCondition = left ; rightCondition = право ; } public override bool IsSatisfiedBy ( объект- кандидат ) { return leftCondition . IsSatisfiedBy ( кандидат ) && rightCondition . IsSatisfiedBy ( кандидат ) ! = True ; } } открытый класс OrSpecification : CompositeSpecification { private ISpecification leftCondition ; private ISpecification rightCondition ; общедоступная спецификация OrSpecification ( спецификация IS слева , спецификация IS справа ) { leftCondition = left ; rightCondition = право ; } public override bool IsSatisfiedBy ( объект- кандидат ) { return leftCondition . IsSatisfiedBy ( кандидат ) || rightCondition . IsSatisfiedBy ( кандидат ); } } открытый класс OrNotSpecification : CompositeSpecification { частная ISpecification leftCondition ; private ISpecification rightCondition ; общедоступная спецификация OrNotSpecification ( ISpecification слева , ISpecification справа ) { leftCondition = left ; rightCondition = право ; } public override bool IsSatisfiedBy ( объект- кандидат ) { return leftCondition . IsSatisfiedBy ( кандидат ) || rightCondition . IsSatisfiedBy ( кандидат ) ! = True ; } } открытый класс NotSpecification : CompositeSpecification { закрытый ISpecification Wrapped ; общедоступная NotSpecification ( ISpecification x ) { Wrapped = x ; } public override bool IsSatisfiedBy ( объект- кандидат ) { return ! Завернутый . IsSatisfiedBy ( кандидат ); } }
C # 6.0 с универсальными шаблонами [ править ]
общедоступный интерфейс ISpecification < T > { bool IsSatisfiedBy ( T кандидат ); ISpecification < T > And ( ISpecification < T > other ); ISpecification < T > AndNot ( ISpecification < T > other ); ISpecification < T > или ( ISpecification < T > other ); ISpecification < T > OrNot ( ISpecification < T > other ); IS Спецификация < T > Not (); } общедоступный абстрактный класс LinqSpecification < T > : CompositeSpecification < T > { общедоступное абстрактное выражение < Func < T , bool >> AsExpression (); public override bool IsSatisfiedBy ( T кандидат ) => AsExpression (). Compile () ( кандидат ); } открытый абстрактный класс CompositeSpecification < T > : ISpecification < T > { public abstract bool IsSatisfiedBy ( T кандидат ); public ISpecification < T > And ( ISpecification < T > other ) => new AndSpecification < T > ( this , other ); общедоступная спецификация IS < T > AndNot ( ISpecification < T > other ) => новый AndNotSpecification < T > ( this , other ); public ISpecification < T > Or ( ISpecification < T > other ) => new OrSpecification < T > ( this , other ); public ISpecification < T > OrNot ( ISpecification <T > другой ) => новый OrNotSpecification < T > ( этот , другой ); общедоступная спецификация IS < T > Not () => новая спецификация NotSpecification < T > ( this ); } открытый класс AndSpecification < T > : CompositeSpecification < T > { ISpecification < T > left ; IСпецификация < T > правая ; public AndSpecification ( ISpecification < T > слева , ISpecification < T > справа ) { this . left = left ; это . right = право ; } public override bool IsSatisfiedBy ( T кандидат ) => left . IsSatisfiedBy ( кандидат ) && верно . IsSatisfiedBy ( кандидат ); } открытый класс AndNotSpecification < T > : CompositeSpecification < T > { ISpecification < T > left ; IСпецификация < T > правая ; public AndNotSpecification ( ISpecification < T > слева , ISpecification < T > справа ) { this . left = left ; это . right = право ; } public override bool IsSatisfiedBy ( T кандидат ) => left . IsSatisfiedBy ( кандидат ) && ! правильно . IsSatisfiedBy ( кандидат ); } открытый класс OrSpecification < T > : CompositeSpecification < T > { ISpecification < T > left ; IСпецификация < T > правая ; public OrSpecification ( ISpecification < T > слева , ISpecification < T > справа ) { this . left = left ; это . right = право ; } public override bool IsSatisfiedBy ( T кандидат ) => left . IsSatisfiedBy ( кандидат ) || правильно . IsSatisfiedBy ( кандидат ); } открытый класс OrNotSpecification < T > : CompositeSpecification < T > { ISpecification < T > left ; IСпецификация < T > правая ; public OrNotSpecification ( ISpecification < T > слева , ISpecification < T > справа ) { this . left = left ; это . right = право ; } public override bool IsSatisfiedBy ( T кандидат ) => left . IsSatisfiedBy ( кандидат ) || ! правильно . IsSatisfiedBy ( кандидат ); } открытый класс NotSpecification < T > : CompositeSpecification < T > { ISpecification < T > другой ; public NotSpecification ( ISpecification < T > other ) => this . другое = другое ; public override bool IsSatisfiedBy ( T кандидат ) => ! другое . IsSatisfiedBy ( кандидат); }
Python [ править ]
from abc import abstractmethod from dataclasses import dataclass from typing import Anyclass BaseSpecification : @abstractmethod def is_satisfied_by ( self , кандидат : Any ) -> bool : raise NotImplementedError () def and_ ( self , other : "BaseSpecification" ) -> "AndSpecification" : return AndSpecification ( self , other ) def or_ ( self , other : "BaseSpecification" ) -> "OrSpecification" : return OrSpecification ( self , other ) def not_ ( self ) -> "NotSpecification" : вернуть NotSpecification ( self )@dataclass ( замороженный = True ) класс AndSpecification ( BaseSpecification ): первый : BaseSpecification, второй : BaseSpecification def is_satisfied_by ( self , кандидат : Any ) -> bool : return self . первый . is_satisfied_by ( кандидат ) и себя . второй . is_satisfied_by ( кандидат )@dataclass ( frozen = True ) class OrSpecification ( BaseSpecification ): первый : BaseSpecification, второй : BaseSpecification def is_satisfied_by ( self , кандидат : Any ) -> bool : return self . первый . is_satisfied_by ( кандидат ) или сам . второй . is_satisfied_by ( кандидат )@dataclass ( frozen = True ) класс NotSpecification ( BaseSpecification ): тема : BaseSpecification def is_satisfied_by ( self , кандидат : Any ) -> bool : return not self . предмет . is_satisfied_by ( кандидат )
Пример использования [ править ]
В следующем примере мы получаем счета и отправляем их в коллекторское агентство, если
- они просрочены,
- уведомления были отправлены, и
- они еще не работают с коллекторским агентством.
Этот пример предназначен для демонстрации конечного результата объединения логики.
В этом примере использования предполагается, что ранее определенный класс OverdueSpecification выполняется, когда срок оплаты счета составляет 30 дней или старше, класс NoticeSentSpecification, который выполняется, когда клиенту отправлены три уведомления, и класс InCollectionSpecification, который выполняется, когда счет-фактура уже отправлено в коллекторское агентство. Реализация этих классов здесь не важна.
Используя эти три спецификации, мы создали новую спецификацию под названием SendToCollection, которая будет удовлетворена, когда счет-фактура просрочен, когда уведомления были отправлены клиенту и еще не отправлены в коллекторское агентство.
var OverDue = новая спецификация OverDue (); var NoticeSent = new NoticeSentSpecification (); var InCollection = новая спецификация InCollection ();// пример логической цепочки шаблона спецификации var SendToCollection = OverDue . И ( Уведомление отправлено ). И ( InCollection . Not ());var InvoiceCollection = Сервис . GetInvoices ();Еогеасп ( вар currentInvoice в InvoiceCollection ) { если ( SendToCollection . IsSatisfiedBy ( currentInvoice )) { currentInvoice . SendToCollection (); } }
Ссылки [ править ]
- Эванс, Эрик (2004). Доменно-ориентированный дизайн . Эддисон-Уэсли. п. 224.
Внешние ссылки [ править ]
- Спецификации Эрика Эванса и Мартина Фаулера
- Шаблон спецификации: грунтовка Мэтта Бертера
- Шаблон спецификации: введение из четырех частей с использованием VB.Net Ричарда Далтона
- Шаблон спецификации в PHP, автор Моше Бревда
- Спецификация доктрины Happyr в PHP от Happyr
- Шаблон спецификации в Swift от Саймона Страндгаарда
- Шаблон спецификации в TypeScript и JavaScript от Тьяго Дельгадо Пинто
- шаблон спецификации во Flash ActionScript 3 от Рольфа Фрейденбергера