stringtranslate.com

Спецификация шаблона

Шаблон спецификации в UML

В компьютерном программировании шаблон спецификации — это конкретный шаблон проектирования программного обеспечения , посредством которого бизнес-правила могут быть рекомбинированы путем объединения бизнес-правил вместе с использованием булевой логики . Шаблон часто используется в контексте проектирования, ориентированного на предметную область .

Шаблон спецификации описывает бизнес-правило, которое можно комбинировать с другими бизнес-правилами. В этом шаблоне единица бизнес-логики наследует свою функциональность от абстрактного агрегатного класса Composite Specification. Класс Composite Specification имеет одну функцию IsSatisfiedBy, которая возвращает логическое значение. После создания экземпляра спецификация «связывается» с другими спецификациями, что делает новые спецификации легко поддерживаемыми, но в то же время высоконастраиваемой бизнес-логикой. Кроме того, при создании экземпляра бизнес-логика может, посредством вызова метода или инверсии управления , изменить свое состояние, чтобы стать делегатом других классов, таких как хранилище персистентности.

В результате выполнения композиции высокоуровневой бизнес-логики/логики предметной области во время выполнения шаблон «Спецификация» является удобным инструментом для преобразования специальных критериев поиска пользователей в низкоуровневую логику для обработки репозиториями.

Поскольку спецификация представляет собой инкапсуляцию логики в форме, пригодной для повторного использования, ее очень просто тщательно тестировать с помощью модулей, и при использовании в этом контексте она также является реализацией шаблона скромного объекта.

Примеры кода

С#

открытый интерфейс ISpecification { bool IsSatisfiedBy ( объект -кандидат ); ISpecification And ( ISpecification other ); ISpecification AndNot ( ISpecification other ); ISpecification Or ( ISpecification other ); ISpecification OrNot ( ISpecification other ); ISpecification Not (); }                   открытый абстрактный класс CompositeSpecification : ISpecification { открытый абстрактный bool IsSatisfiedBy ( объект- кандидат );            public ISpecification And ( ISpecification other ) { return new AndSpecification ( this , other ); }           public ISpecification AndNot ( ISpecification other ) { return new AndNotSpecification ( this , other ); }           public ISpecification Or ( ISpecification other ) { return new OrSpecification ( this , other ); }           public ISpecification OrNot ( ISpecification other ) { return new OrNotSpecification ( this , other ); }           public ISpecification Not () { return new NotSpecification ( this ); } }        открытый класс AndSpecification : CompositeSpecification { частный ISpecification leftCondition ; частный ISpecification rightCondition ;            public AndSpecification ( ISpecification left , ISpecification right ) { leftCondition = left ; rightCondition = right ; }              public override bool IsSatisfiedBy ( object candidate ) { return leftCondition.IsSatisfiedBy ( candidate ) && rightCondition.IsSatisfiedBy ( candidate ) ; } }           открытый класс AndNotSpecification : CompositeSpecification { частный ISpecification leftCondition ; частный ISpecification rightCondition ;            public AndNotSpecification ( ISpecification left , ISpecification right ) { leftCondition = left ; rightCondition = right ; }              public override bool IsSatisfiedBy ( object candidate ) { return leftCondition.IsSatisfiedBy ( candidate ) && rightCondition.IsSatisfiedBy ( candidate ) ! = true ; } }             открытый класс OrSpecification : CompositeSpecification { частный ISpecification leftCondition ; частный ISpecification rightCondition ;           public OrSpecification ( ISpecification left , ISpecification right ) { leftCondition = left ; rightCondition = right ; }              public override bool IsSatisfiedBy ( object candidate ) { return leftCondition.IsSatisfiedBy ( candidate ) || rightCondition.IsSatisfiedBy ( candidate ) ; } }           открытый класс OrNotSpecification : CompositeSpecification { частный ISpecification leftCondition ; частный ISpecification rightCondition ;           public OrNotSpecification ( ISpecification left , ISpecification right ) { leftCondition = left ; rightCondition = right ; }              public override bool IsSatisfiedBy ( object candidate ) { return leftCondition.IsSatisfiedBy ( candidate ) || rightCondition.IsSatisfiedBy ( candidate ) ! = true ; } }             открытый класс NotSpecification : CompositeSpecification { частный ISpecification Wrapped ;         public NotSpecification ( ISpecification x ) { Обернутый = x ; }         public override bool IsSatisfiedBy ( object candidate ) { return ! Wrapped . IsSatisfiedBy ( candidate ); } }         

C# 6.0 с дженериками

открытый интерфейс ISpecification < T > { bool IsSatisfiedBy ( T candidate ) ; ISpecification < T > And ( ISpecification < T > other ) ; ISpecification < T > AndNot ( ISpecification < T > other ) ; ISpecification < T > OrNot ( ISpecification < T > other ) ; ISpecification < T > Not ( ) ; }                   public abstract class LinqSpecification < T > : CompositeSpecification < T > { public abstract Expression < Func < T , bool >> AsExpression (); public override bool IsSatisfiedBy ( T candidate ) => AsExpression (). Compile ()( candidate ); }                 public abstract class CompositeSpecification <T> : ISpecification <T> { public abstract bool IsSatisfiedBy ( T candidate ) ; public ISpecification <T> And ( ISpecification <T> other ) = > new AndSpecification <T> ( this , other ) ; public ISpecification <T> AndNot ( ISpecification <T> other ) = > new AndNotSpecification <T> ( this , other ) ; public ISpecification <T> Or ( ISpecification <T> other ) = > new OrSpecification <T> ( this , other ) ; public ISpecification <T> OrNot ( ISpecification <T> other ) = > new OrNotSpecification <T> ( this , other ) ; public ISpecification <T> Not ( ) = > new NotSpecification <T> ( this ) ; }                                                открытый класс AndSpecification < T > : CompositeSpecification < T > { ISpecification < T > слева ; ISpecification < T > справа ;         public AndSpecification ( ISpecification <T> left , ISpecification <T> right ) { this.left = left ; this.right = right ; }             public override bool IsSatisfiedBy ( T candidate ) = > left.IsSatisfiedBy ( candidate ) && right.IsSatisfiedBy ( candidate ) ; }        открытый класс AndNotSpecification < T > : CompositeSpecification < T > { ISpecification < T > слева ; ISpecification < T > справа ;         public AndNotSpecification ( ISpecification <T> left , ISpecification <T> right ) { this.left = left ; this.right = right ; }             public override bool IsSatisfiedBy ( T candidate ) = > left.IsSatisfiedBy ( candidate ) && ! right.IsSatisfiedBy ( candidate ) ; }        открытый класс OrSpecification < T > : CompositeSpecification < T > { ISpecification < T > слева ; ISpecification < T > справа ;         public OrSpecification ( ISpecification <T> left , ISpecification <T> right ) { this.left = left ; this.right = right ; }             public override bool IsSatisfiedBy ( T candidate ) = > left.IsSatisfiedBy ( candidate ) || right.IsSatisfiedBy ( candidate ) ; } public class OrNotSpecification <T> : CompositeSpecification <T> { ISpecification <T> left ; ISpecification <T> right ;                 public OrNotSpecification ( ISpecification <T> left , ISpecification <T> right ) { this.left = left ; this.right = right ; }             public override bool IsSatisfiedBy ( T candidate ) = > left.IsSatisfiedBy ( candidate ) || ! right.IsSatisfiedBy ( candidate ) ; }        public class NotSpecification <T> : CompositeSpecification <T> { ISpecification <T> other ; public NotSpecification ( ISpecification <T> other ) = > this.other = other ; public override bool IsSatisfiedBy ( T candidate ) = > ! other.IsSatisfiedBy ( candidate ) ; }                    

Питон

из  abc  импорт  ABC ,  абстрактный метод из  dataclasses  импорт  dataclass из  typing  импорт  Anyкласс  BaseSpecification ( ABC ):  @abstractmethod  def  is_satisfied_by ( self ,  candidate :  Any )  ->  bool :  raise  NotImplementedError () def  __call__ ( self ,  candidate :  Any )  - >  bool :  return  self.is_satisfied_by ( candidate ) def  __and__ ( self ,  other :  "BaseSpecification" )  ->  "AndSpecification" :  return  AndSpecification ( self ,  other ) def  __or__ ( self ,  other :  "BaseSpecification" )  ->  "OrSpecification" :  return  OrSpecification ( self ,  other ) def  __neg__ ( self )  ->  "NotSpecification" :  return  NotSpecification ( self )@dataclass ( frozen = True ) класс  AndSpecification ( BaseSpecification ):  первый :  BaseSpecification  второй :  BaseSpecification def  is_satisfied_by ( self ,  candidate :  Any )  -  > bool :  возвращает  self.first.is_satisfied_by ( candidate ) и self.second.is_satisfied_by ( candidate )  @dataclass ( frozen = True ) класс  OrSpecification ( BaseSpecification ):  первый :  BaseSpecification  второй :  BaseSpecification def  is_satisfied_by ( self ,  candidate :  Any )  - >  bool :  return  self.first.is_satisfied_by ( candidate ) или self.second.is_satisfied_by ( candidate )  @dataclass ( frozen = True ) класс  NotSpecification ( BaseSpecification ):  субъект :  BaseSpecification def  is_satisfied_by ( self ,  candidate :  Any )  - >  bool :  return  not  self.subject.is_satisfied_by ( candidate )

С++

template < class T > class ISpecification { public : virtual ~ ISpecification ( ) = default ; virtual bool IsSatisfiedBy ( T Candidate ) const = 0 ; virtual ISpecification <T> * And ( const ISpecification <T> & Other ) const = 0 ; virtual ISpecification <T> * AndNot ( const ISpecification <T> & Other ) const = 0 ; virtual ISpecification <T> * Or ( const ISpecification <T> & Other ) const = 0 ; virtual ISpecification <T> * OrNot ( const ISpecification <T> & Other ) const = 0 ; virtual ISpecification <T> * Not ( ) const = 0 ; } ;                                             шаблон < класс T > класс CompositeSpecification : public ISpecification <T> { public : virtual bool IsSatisfiedBy ( T Candidate ) const override = 0 ;             virtual ISpecification < T >* And ( const ISpecification < T >& Other ) const override ; virtual ISpecification < T >* AndNot ( const ISpecification < T >& Other ) const override ; virtual ISpecification < T >* Or ( const ISpecification < T >& Other ) const override ; virtual ISpecification < T >* OrNot ( const ISpecification < T >& Other ) const override ; virtual ISpecification < T >* Not () const override ; };                            template < class T > class AndSpecification final : public CompositeSpecification < T > { public : const ISpecification < T >& Left ; const ISpecification < T >& Right ;           AndSpecification ( const ISpecification < T >& InLeft , const ISpecification < T >& InRight ) : Левый ( InLeft ), Правый ( InRight ) { }         virtual bool IsSatisfiedBy ( T Candidate ) const override { return Left.IsSatisfiedBy ( Candidate ) && Right.IsSatisfiedBy ( Candidate ) ; } } ;        template < class T > ISpecification < T >* CompositeSpecification < T >:: And ( const ISpecification < T >& Other ) const { return new AndSpecification < T > ( * this , Other ); }         template < class T > class AndNotSpecification final : public CompositeSpecification < T > { public : const ISpecification < T >& Left ; const ISpecification < T >& Right ;           AndNotSpecification ( const ISpecification < T >& InLeft , const ISpecification < T >& InRight ) : Левый ( InLeft ), Правый ( InRight ) { }         virtual bool IsSatisfiedBy ( T Candidate ) const override { return Left.IsSatisfiedBy ( Candidate ) && ! Right.IsSatisfiedBy ( Candidate ) ; } } ;        template < class T > class OrSpecification final : public CompositeSpecification < T > { public : const ISpecification < T >& Left ; const ISpecification < T >& Right ;           ИлиСпецификация ( const ISpecification < T >& InLeft , const ISpecification < T >& InRight ) : Слева ( InLeft ), Справа ( InRight ) { }         virtual bool IsSatisfiedBy ( T Candidate ) const override { return Left.IsSatisfiedBy ( Candidate ) || Right.IsSatisfiedBy ( Candidate ) ; } } ;        template < class T > class OrNotSpecification final : public CompositeSpecification < T > { public : const ISpecification < T >& Left ; const ISpecification < T >& Right ;           ИлиНеСпецификация ( const ISpecification < T >& InLeft , const ISpecification < T >& InRight ) : Левый ( InLeft ), Правый ( InRight ) { }         virtual bool IsSatisfiedBy ( T Candidate ) const override { return Left.IsSatisfiedBy ( Candidate ) || ! Right.IsSatisfiedBy ( Candidate ) ; } } ;        шаблон < класс T > класс NotSpecification final : public CompositeSpecification <T> { public : const ISpecification <T> & Other ;         NotSpecification ( const ISpecification < T >& InOther ) : Другое ( InOther ) { }     virtual bool IsSatisfiedBy ( T Candidate ) const override { return ! Other.IsSatisfiedBy ( Candidate ) ; } } ;      template < class T > ISpecification < T >* CompositeSpecification < T >:: AndNot ( const ISpecification < T >& Other ) const { return new AndNotSpecification < T > ( * this , Other ); }         template < class T > ISpecification < T >* CompositeSpecification < T >:: Or ( const ISpecification < T >& Other ) const { return new OrSpecification < T > ( * this , Other ); }         template < class T > ISpecification < T >* CompositeSpecification < T >:: OrNot ( const ISpecification < T >& Other ) const { return new OrNotSpecification < T > ( * this , Other ); }         шаблон < класс T > ISpecification < T >* CompositeSpecification < T >:: Not () const { return new NotSpecification < T > ( * this ); }      

Машинопись

экспорт интерфейса ISpecification { isSatisfiedBy ( candidate : unknown ) : boolean ; and ( other : ISpecification ) : ISpecification ; andNot ( other : ISpecification ) : ISpecification ; or ( other : ISpecification ) : ISpecification ; orNot ( other : ISpecification ) : ISpecification ; not () : ISpecification ; }                    экспорт абстрактного класса CompositeSpecification реализует ISpecification { abstract isSatisfiedBy ( candidate : unknown ) : boolean ;           и ( другой : ISpecification ) : ISpecification { return new AndSpecification ( этот , другой ); }         andNot ( other : ISpecification ) : ISpecification { return new AndNotSpecification ( this , other ); }         или ( другой : ISpecification ) : ISpecification { return new OrSpecification ( этот , другой ); }         илиНе ( другой : ISpecification ) : ISpecification { вернуть новый OrNotSpecification ( этот , другой ); }         не () : ISpecification { return new NotSpecification ( this ); } }      экспорт класса AndSpecification расширяет CompositeSpecification { конструктор ( private leftCondition : ISpecification , private rightCondition : ISpecification ) { super (); }               isSatisfiedBy ( кандидат : неизвестен ) : boolean { верните это . левое состояние . isSatisfiedBy ( кандидат ) && this . правильное состояние . isSatisfiedBy ( кандидат ); } }        экспорт класса AndNotSpecification расширяет CompositeSpecification { конструктор ( private leftCondition : ISpecification , private rightCondition : ISpecification ) { super (); }               isSatisfiedBy ( кандидат : неизвестен ) : boolean { верните это . левое состояние . isSatisfiedBy ( кандидат ) && this . правильное состояние . isSatisfiedBy ( кандидат ) !== true ; } }          экспорт класса OrSpecification расширяет CompositeSpecification { конструктор ( private leftCondition : ISpecification , private rightCondition : ISpecification ) { super (); }               isSatisfiedBy ( кандидат : неизвестен ) : boolean { верните это . левое состояние . isSatisfiedBy ( кандидат ) || этот . правильное состояние . isSatisfiedBy ( кандидат ); } }        экспорт класса OrNotSpecification расширяет CompositeSpecification { конструктор ( private leftCondition : ISpecification , private rightCondition : ISpecification ) { super (); }               isSatisfiedBy ( кандидат : неизвестен ) : boolean { верните это . левое состояние . isSatisfiedBy ( кандидат ) || этот . правильное состояние . isSatisfiedBy ( кандидат ) !== true ; } }          экспорт класса NotSpecification расширяет CompositeSpecification { конструктор ( частный обернутый : ISpecification ) { super (); }            isSatisfiedBy ( кандидат : неизвестный ) : логическое значение { return ! this.wrapped.isSatisfiedBy ( кандидат ) ; } }      

Пример использования

В следующем примере счета-фактуры извлекаются и отправляются в агентство по взысканию задолженностей, если:

  1. они просрочены,
  2. уведомления были отправлены, и
  3. они еще не работают в коллекторском агентстве.

Этот пример призван продемонстрировать результат того, как логика «связывается» воедино.

Этот пример использования предполагает ранее определенный OverdueSpecificationкласс, который удовлетворяется, когда срок оплаты счета составляет 30 дней или больше, NoticeSentSpecificationкласс, который удовлетворяется, когда три уведомления были отправлены клиенту, и класс InCollectionSpecification, который удовлетворяется, когда счет уже был отправлен в агентство по взысканию. Реализация этих классов здесь не важна.

Используя эти три спецификации, мы создали новую спецификацию под названием SendToCollection, которая будет выполняться в случае, если счет просрочен, уведомления отправлены клиенту и еще не находятся в коллекторском агентстве.

var overDue = new OverDueSpecification (); var notificationSent = new NoticeSentSpecification (); var inCollection = new InCollectionSpecification ();            // Пример логической цепочки шаблона спецификации var sendToCollection = overDue.And ( notSent ) .And ( inCollection.Not ( ) ) ;   var invoiceCollection = Service.GetInvoices ( ) ;   foreach ( var currentInvoice in invoiceCollection ) { if ( sendToCollection . IsSatisfiedBy ( currentInvoice )) { currentInvoice . SendToCollection (); } }         

Ссылки

Внешние ссылки