Tolk (designmønster)

Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den version , der blev gennemgået den 5. april 2017; checks kræver 12 redigeringer .
Tolk
tolk
Type adfærdsmæssige
Formål løser et ofte opstået problem med forbehold for ændringer
Beskrevet i Design Patterns Ja

En tolk er et  adfærdsmæssigt designmønster , der løser en ofte stødt, men med forbehold for ændringer, opgave. Også kendt som Lille (lille) sprog

Problem

Der er en hyppigt forekommende opgave, der kan ændres.

Løsning

Opret en tolk, der løser dette problem.

Fordele

Grammatikken bliver let at udvide og ændre, implementeringerne af klasserne, der beskriver noderne i det abstrakte syntakstræ, ligner hinanden (let kodet). Du kan nemt ændre, hvordan udtryk evalueres.

Ulemper

At opretholde en grammatik med et stort antal regler er svært.

Eksempel

Opgaven med at søge efter strenge efter mønster kan løses ved at skabe en tolk, der definerer sprogets grammatik. "Klienten" bygger en sætning i form af et abstrakt syntakstræ, i hvis noder der er objekter af klasserne "TerminalExpression" og "NonterminalExpression" (rekursiv), derefter initialiserer "Clienten" konteksten og kalder Parse( kontekst) operation. Hver node af typen "NonterminalExpression" definerer en Parse-operation for hvert underudtryk. For klassen "NonTerminalExpression" bestemmer Parse-operationen basen for rekursionen. "AbstractExpression" definerer den abstrakte parse-operation, der er fælles for alle noder i det abstrakte syntakstræ. "Kontekst" indeholder information globalt for tolken.

C#

Kildetekst i C# bruger System ; ved hjælp af System.Collections ; navneområde 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" } } } ; // Output: sandt input . Værdi = "fire" ; udtryk . Fortolke ( kontekst ); Konsol . WriteLine ( context.result.pop ( ) ) ; _ // Output: falsk input . Værdi = "44" ; udtryk . Fortolke ( kontekst ); Konsol . WriteLine ( context.result.pop ( ) ) ; _ } } class Context { public Stack < string > Result = new Stack < string >(); } interface Udtryk { void Fortolk ( Kontekst kontekst ); } abstrakt klasse OperatorExpression : Udtryk { offentlig Udtryk Venstre { private get ; sæt ; } public Expression Right { private get ; sæt ; } public void Fortolk ( kontekstkontekst ) { Venstre . _ Fortolke ( kontekst ); string leftValue = kontekst . resultat . pop (); Højre . Fortolke ( kontekst ); streng rightValue = kontekst . resultat . pop (); DoInterpret ( kontekst , leftValue , rightValue ); } beskyttet abstrakt void DoInterpret ( Kontekstkontekst , streng leftValue , streng rightValue ) ; } klasse EqualsExpression : OperatorExpression { protected override void DoInterpret ( Context context , string leftValue , string rightValue ) { kontekst . resultat . Push ( leftValue == rightValue ? "true" : "false" ); } } klasse OrExpression : OperatorExpression { protected override void DoInterpret ( Context context , string leftValue , string rightValue ) { context . resultat . Push ( leftValue == "true" || rightValue == "true" ? "true" : "false" ); } } class MyExpression : Expression { public string Value { private get ; sæt ; } public void Fortolk ( Kontekst kontekst ) { kontekst . resultat . Skub ( Værdi ); } } }

Python

Kildekode i Python __doc__ = ''' Et system til at evaluere og manipulere booleske udtryk. Eksempel fra Gang of Four - "Design Patterns: Elements of Genusable Object-Oriented Software" ''' fra abc import ABCMeta , abstrakt metode class Context : """ Runtime kontekst for tolken """ def __init__ ( selv , variabler : dict = {}) -> Ingen : """ Konstruktør. :param variabler: en ordbog over match mellem variabelnavne og deres værdier " "" self ._variables = variables klasse ContextException ( Undtagelse ): """ Undtagelse smidt i tilfælde af forkert arbejde med denne klasse """ pass def opslag ( selv , navn : str ) -> bool : """ Henter værdien af ​​en variabel ved dens navn :param navn: variabelnavn """ hvis navn i sig selv . _variabler : returnerer selv . _variabler [ navn ] hæver sig selv . ContextException ( 'Ukendt variabel {} ' . format ( navn )) def assign ( selv , navn : str , værdi : bool ) -> Ingen : """ Tildeler en værdi til en variabel ved dens navn :param navn: variabel navn :param værdi: variabel værdi " "" self ._variables [ navn ] = værdi klasse BooleanExp ( metaclass = ABCMeta ): """ Abstrakt boolesk udtryk """ @abstractmethod def evaluate ( selv , kontekst : kontekst ) -> bool : """ Få resultatet af det boolske udtryk """ pass klasse ConstantExp ( BooleanExp ): """ Boolesk konstant """ def __init__ ( selv , værdi : bool ): """ Konstruktør. :param værdi: udtryksværdi (Sand eller Falsk) "" ​​" self ._value = værdi def evaluere ( selv , kontekst : kontekst ): returnere selv . _værdi klasse VariableExp ( BooleanExp ): """ Boolesk variabel (værdien af ​​variabler er gemt i fortolkerkontekstobjektet) """ def __init__ ( selv , navn : str ) -> Ingen : """ Konstruktør. :param navn: variabelnavn " "" self ._name = navn def evaluere ( selv , kontekst : kontekst ) -> bool : returnere kontekst . opslag ( selv._navn ) _ _ klasse BinaryOperationExp ( BooleanExp , metaclass = ABCMeta ): """ Abstrakt klasse for binære logiske operationer """ def __init__ ( selv , venstre : BooleanExp , højre : BooleanExp ) -> Ingen : """ Konstruktør. :param venstre: venstre operand :param højre: højre operand " " " selv ._left = venstre selv ._right = højre klasse AndExp ( BinaryOperationExp ): """ Konjunktion """ def evaluere ( selv , kontekst : kontekst ) -> bool : returnere selv . _venstre . evaluere ( kontekst ) og selv . _højre . vurdere ( kontekst ) klasse OrExp ( BinaryOperationExp ): """ Disjunktion """ def evaluere ( selv , kontekst : kontekst ) -> bool : returnere selv . _venstre . evaluere ( kontekst ) eller selv . _højre . vurdere ( kontekst ) klasse NotExp ( BooleanExp ): """ Negativ """ def __init__ ( selv , operand : BooleanExp ) -> Ingen : """ Konstruktør. :param operand: operand, som """ -operationen anvendes på selv _operand = operand def evaluere ( selv , kontekst : kontekst ) -> bool : returner ikke selv . _operand . vurdere ( kontekst ) def execute_test ( context : Context , x : bool , y : bool ) -> Ingen : """ En funktion til at udføre test på vores """ kontekstfortolker . tildele ( 'x' , x ) kontekst . tildel ( 'y' , y ) udtryk = OrExp ( # (True og x) eller (y og (ikke x)) AndExp ( ConstantExp ( True ), VariableExp ( 'x' )), AndExp ( VariableExp ( 'y' ) , NotExp ( VariableExp ( 'x' ))) ) print ( udtryk . evaluere ( kontekst )) if __name__ == '__main__' : print ( 'OUTPUT:' ) context = Context () execute_test ( context , True , False ) execute_test ( context , False , True ) execute_test ( context , False , False ) ''' OUTPUT: Sand Sand Falsk '''

PHP

PHP kildekode <?php /** * Eksempel på tolkemønster ved hjælp af komposition */ abstrakt klasse Udtryk { privat statisk $_count = 0 ; privat $_key = null ; offentlig abstrakt funktion fortolke ( InterpreterContext $context ); public function getKey () { if ( ! isset ( $this -> _key ) ) { self :: $_count ++ ; $this -> _key = self :: $_count ; } returner $this -> _key ; } } klasse LiteralExpression udvider udtryk { privat $_værdi = null ; offentlig funktion __construct ( $værdi ) { $this -> _value = $værdi ; } public function interpret ( InterpreterContext $context ) { $context -> replace ( $this , $this -> _value ); } } klasse VariableExpression udvider udtryk { privat $_name = null ; privat $_val = null ; offentlig funktion __construct ( $navn , $val = null ) { $this -> _name = $navn ; $this -> _val = $val ; } public function interpret ( InterpreterContext $context ) { if ( ! is_null ( $this -> _val ) ) $context -> replace ( $this , $this -> _val ); } public function setValue ( $værdi ) { $this -> _val = $værdi ; } public function getKey () { return $this -> _name ; } } abstrakt klasse OperatorExpression udvider udtryk { beskyttet $venstreoperand = null ; beskyttet $rightoperand = null ; public function __construct ( Udtryk $venstreoperand , Udtryk $rightoperand ) { $this -> leftoperand = $venstreoperand ; $this -> højreoperand = $højreoperand ; } public function interpret ( InterpreterContext $context ) { $this -> leftoperand -> interpret ( $context ); $this -> højreoperand -> fortolk ( $kontekst ); $resultleft = $kontekst -> opslag ( $this -> venstreoperand ); $resultright = $kontekst -> opslag ( $this -> højreoperand ); $this -> doInterpret ( $context , $ resultleft , $resultright ); } beskyttet abstrakt funktion doInterpret ( InterpreterContext $context , $ resultleft , $resultright ); } klasse EqualsExpression udvider OperatorExpression { beskyttet funktion doInterpret ( InterpreterContext $context , $ resultleft , $resultright ) { $context -> replace ( $this , $resultleft == $resultright ); } } klasse BooleanOrExpression udvider OperatorExpression { beskyttet funktion doInterpret ( InterpreterContext $context , $ resultleft , $resultright ) { $context -> replace ( $this , $resultleft || $resultright ); } } klasse BooleanAndExpression udvider OperatorExpression { beskyttet funktion doInterpret ( InterpreterContext $context , $ resultleft , $resultright ) { $context -> replace ( $this , $resultleft && $resultright ); } } klasse InterpreterContext { private $_expressionstore = array (); public function replace ( udtryk $exp , $value ) { $this -> _expressionstore [ $exp -> getKey ()] = $værdi ; } public function lookup ( Udtryk $exp ) { return $this -> _expressionstore [ $exp -> getKey ()]; } } $context = new InterpreterContext (); $input = new VariableExpression ( 'input' ); $statement = new BooleanOrExpression ( nyt EqualsExpression ( $input , new LiteralExpression ( "fire" ) ), nyt EqualsExpression ( $input , new LiteralExpression ( "4" ) ) ); foreach ( array ( "fire" , "4" , "52" ) ​​som $værdi ) { $input -> setValue ( $værdi ); print " { $værdi } :<br>" ; $statement -> fortolk ( $kontekst ); print $context -> lookup ( $statement ) ? "Meets<br><br>" : "Sammenser ikke<br><br>" ; } ?>

Se også