Interpret (model de proiectare)

Versiunea actuală a paginii nu a fost încă examinată de colaboratori experimentați și poate diferi semnificativ de versiunea revizuită la 5 aprilie 2017; verificările necesită 12 modificări .
Interpret
interpret
Tip de comportamental
Scop rezolvă o problemă frecvent întâlnită, supusă modificării
Descris în Design Patterns da

Un interpret este un  model de design comportamental care rezolvă o sarcină frecvent întâlnită, dar supusă schimbării. Cunoscut și sub numele de Limbă Mică

Problemă

Există o sarcină care apare frecvent, care poate fi schimbată.

Soluție

Creați un interpret care să rezolve această problemă.

Beneficii

Gramatica devine ușor de extins și schimbat, implementările claselor care descriu nodurile arborelui de sintaxă abstractă sunt similare (cod ușor). Puteți schimba cu ușurință modul în care sunt evaluate expresiile.

Dezavantaje

Menținerea unei gramatici cu un număr mare de reguli este dificilă.

Exemplu

Sarcina de căutare a șirurilor după model poate fi rezolvată prin crearea unui interpret care definește gramatica limbii. „Clientul” construiește o propoziție sub forma unui arbore de sintaxă abstractă, în nodurile căruia se află obiecte din clasele „TerminalExpression” și „NonterminalExpression” (recursiv), apoi „Client” inițializează contextul și apelează Parse( Context) operare. Fiecare nod de tip „NonterminalExpression” definește o operație de analiză pentru fiecare subexpresie. Pentru clasa „NonTerminalExpression”, operația Parse determină baza recursiunii. „AbstractExpression” definește operația abstractă Parse comună tuturor nodurilor din arborele de sintaxă abstractă. „Context” conține informații globale pentru interpret.

C#

Text sursă în C# folosind System ; folosind System.Collections ; namespace DoFactory.GangOfFour.Interpreter.Structural { class Program { static void Main () { var context = new Context (); var input = new MyExpression (); var expression = new OrExpression { Left = new EqualsExpression { Left = input , Right = new MyExpression { Value = "4" } } }, Right = new EqualsExpression { Left = input , Right = new MyExpression { Value = "four" } } } ; // Ieșire: intrare adevărată . Valoare = „patru” ; expresie . Interpreta ( context ); Consola . WriteLine ( context.result.pop ( ) ) ; _ // Ieșire: intrare falsă . Valoare = "44" ; expresie . Interpreta ( context ); Consola . WriteLine ( context.result.pop ( ) ) ; _ } } clasă Context { public Stack < șir > Rezultat = new Stack < șir >(); } interfață Expresia { void Interpret ( Context context ); } clasa abstractă OperatorExpression : Expresie { public Expression Left { private get ; set ; } public Expression Right { private get ; set ; } public void Interpretare ( Context context ) { Stânga . Interpreta ( context ); șir leftValue = context . rezultat . pop (); corect . Interpreta ( context ); șir rightValue = context . rezultat . pop (); DoInterpret ( context , leftValue , rightValue ); } protected abstract void DoInterpret ( Context context , string leftValue , string rightValue ); } class EqualsExpression : OperatorExpression { protected override void DoInterpret ( context context , șir leftValue , șir rightValue ) { context . rezultat . Push ( leftValue == rightValue ? „adevărat” : „fals” ); } } class OrExpression : OperatorExpression { protected override void DoInterpret ( context context , șir leftValue , șir rightValue ) { context . rezultat . Push ( leftValue == „adevărat” || rightValue == „adevărat” ? „adevărat” : „fals” ); } } class MyExpression : Expresie { public string Valoare { private get ; set ; } public void Interpret ( Context context ) { context . rezultat . Push ( Valoare ); } } }

Python

Cod sursă în Python __doc__ = ''' Un sistem pentru evaluarea și manipularea expresiilor booleene. Exemplu din Gang of Four - „Modele de design: Elemente de software reutilizabil orientat pe obiecte” ''' din abc import ABCMeta , abstractmethod Contextul clasei : """ Contextul de rulare al interpretului """ def __init__ ( self , variabile : dict = {}) -> None : """ Constructor. :param variabile: un dicționar de potriviri între numele variabilelor și valorile acestora ​​" "" self ._variables = variabile clasa ContextException ( Excepție ): """ Excepție aruncată în cazul unei lucrări incorecte cu această trecere de clasă """ def lookup ( self , name : str ) -> bool : """ Obține valoarea unei variabile după numele ei :param name: numele variabilei """ dacă numele în self . _variables : returnează self . _variables [ nume ] ridică self . ContextException ( 'variabilă necunoscută {} ' . format ( nume )) def assign ( self , name : str , value : bool ) -> None : """ Atribuie o valoare unei variabile după numele ei :nume param: nume variabilă :valoare param: valoare variabilă " "" self ._variables [ nume ] = valoare clasa BooleanExp ( metaclasa = ABCMeta ): """ Expresie booleană abstractă """ @abstractmethod def evaluate ( self , context : Context ) -> bool : """ Obțineți rezultatul expresiei booleene """ trece clasa ConstantExp ( BooleanExp ): """ Constanta booleană """ def __init__ ( self , value : bool ): """ Constructor. :param value: valoarea expresiei (Adevărat sau Fals) "" " self ._value = valoare def evaluate ( self , context : Context ): return self . _valoare clasa VariableExp ( BooleanExp ): """ Variabilă booleană (valoarea variabilelor este stocată în obiectul context al interpretului) """ def __init__ ( self , name : str ) -> None : """ Constructor. :param name: nume variabilă " "" self ._name = nume def evaluate ( self , context : Context ) -> bool : returnează context . căutare ( self . _name ) clasa BinaryOperationExp ( BooleanExp , metaclasa = ABCMeta ): """ Clasa abstracta pentru operatii logice binare """ def __init__ ( self , stânga : BooleanExp , dreapta : BooleanExp ) -> None : """ Constructor. :param stânga: operand stânga :param dreapta: operand dreapta " " " self ._left = stânga sine ._right = dreapta clasa AndExp ( BinaryOperationExp ): """ Conjuncție """ def evaluate ( self , context : Context ) -> bool : return self . _stânga . evalua ( context ) și sine . _drept . evalua ( context ) clasa OrExp ( BinaryOperationExp ): """ Disjuncție """ def evaluate ( self , context : Context ) -> bool : return self . _stânga . evalua ( context ) sau sine . _drept . evalua ( context ) clasa NotExp ( BooleanExp ): """ Negativ """ def __init__ ( self , operand : BooleanExp ) -> None : """ Constructor. :param operand: operand căruia i se aplică operația """ self _operand = operand def evaluate ( self , context : Context ) -> bool : return not self . _operand . evalua ( context ) def execute_test ( context : Context , x : bool , y : bool ) -> None : """ O funcție pentru a efectua teste pe interpretul nostru de context """ . atribuie ( 'x' , x ) context . atribuiți ( 'y' , y ) expresie = OrExp ( # (Adevărat și x) sau (y și (nu x)) AndExp ( ConstantExp ( Adevărat ), VariableExp ( 'x' )), AndExp ( VariableExp ( 'y' ) , NotExp ( VariableExp ( 'x' ))) ) print ( expresie . evaluate ( context )) if __name__ == '__main__' : print ( 'OUTPUT:' ) context = Context () execute_test ( context , True , False ) execute_test ( context , False , True ) execute_test ( context , False , False ) ''' IEȘIRE: Adevărat Adevărat Fals '''

PHP

Cod sursă PHP <?php /** * Exemplu de model de interpret folosind compoziția */ abstract class Expresie { privat static $_count = 0 ; private $_key = null ; funcția abstractă publică interpreta ( InterpreterContext $context ); funcția publică getKey () { if ( ! isset ( $this -> _key ) ) { self :: $_count ++ ; $this -> _key = self :: $_count ; } returnează $this -> _key ; } } clasa LiteralExpression extinde expresia { private $_value = null ; function public __construct ( $valoare ) { $aceasta -> _valoare = $valoare ; } funcția publică interpreta ( InterpreterContext $context ) { $context -> înlocuire ( $acest , $acest -> _valoare ); } } clasa VariableExpression extinde expresia { private $_name = null ; private $_val = null ; function public __construct ( $nume , $val = null ) { $this -> _name = $nume ; $acest -> _val = $val ; } funcția publică interpreta ( InterpreterContext $context ) { if ( ! is_null ( $this -> _val ) ) $context -> replace ( $this , $this -> _val ); } public function setValue ( $valoare ) { $aceasta -> _val = $valoare ; } public function getKey () { return $this -> _name ; } } clasa abstractă OperatorExpression extinde expresia { protejat $leftoperand = null ; protejat $rightoperand = null ; funcţia publică __construct ( Expresia $operand stânga , Expresie $operand dreapta ) { $acest -> operand stânga = $operand stânga ; $this -> rightoperand = $rightoperand ; } funcția publică interpret ( InterpreterContext $context ) { $this -> leftoperand -> interpret ( $context ); $this -> rightoperand -> interpret ( $context ); $resultleft = $context -> search ( $this -> leftoperand ); $resultright = $context -> search ( $this -> rightoperand ); $this -> doInterpret ( $context , $resultright , $resultright ); } funcția abstractă protejată doInterpret ( InterpreterContext $context , $resultright , $resultright ); } clasa EqualsExpression extinde OperatorExpression { function protected doInterpret ( InterpreterContext $context , $resultright , $resultright ) { $context -> replace ( $this , $resultleft == $resultright ); } } clasa BooleanOrExpression extinde OperatorExpression { funcția protejată doInterpret ( InterpreterContext $context , $resultright , $resultright ) { $context -> înlocuiți ( $this , $resultleft || $resultright ); } } clasa BooleanAndExpression extinde OperatorExpression { funcția protejată doInterpret ( InterpreterContext $context , $resultleft , $resultright ) { $context -> înlocuiți ( $this , $resultleft && $resultright ); } } clasa InterpreterContext { private $_expressionstore = matrice (); funcția publică înlocuiți ( Expresia $exp , $valoare ) { $this -> _expressionstore [ $exp -> getKey ()] = $valoare ; } căutare funcție publică ( Expresia $exp ) { return $this -> _expressionstore [ $exp -> getKey ()]; } } $context = new InterpreterContext (); $input = new VariableExpression ( 'input' ); $statement = new BooleanOrExpression ( nou EqualsExpression ( $input , nou LiteralExpression ( " patru " ) ), nou EqualsExpression ( $input , nou LiteralExpression ( "4" ) ) ); foreach ( array ( "patru" , "4" , "52" ) ​​as $valoare ) { $input -> setValue ( $valoare ); print " { $valoare } :<br>" ; $statement -> interpret ( $context ); print $context -> lookup ( $statement ) ? „Meets<br><br>” : „Nu se potrivește<br><br>” ; } ?>

Vezi și