Tlumočník (designový vzor)

Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od verze recenzované 5. dubna 2017; kontroly vyžadují 12 úprav .
Tlumočník
tlumočník
Typ behaviorální
Účel řeší často se vyskytující problém, který se může změnit
Popsáno v Návrhové vzory Ano

Interpret je behaviorální návrhový vzor  , ​​který řeší často se vyskytující, ale podléhající změnám, úkol. Také známý jako malý (malý) jazyk

Problém

Existuje často se vyskytující úkol, který se může změnit.

Řešení

Vytvořte interpret, který tento problém vyřeší.

Výhody

Gramatika se snadno rozšiřuje a mění, implementace tříd, které popisují uzly abstraktního syntaktického stromu, jsou podobné (snadno kódovatelné). Způsob vyhodnocování výrazů můžete snadno změnit.

Nevýhody

Udržet gramatiku s velkým množstvím pravidel je obtížné.

Příklad

Úkol hledání řetězců podle vzoru lze vyřešit vytvořením interpretu, který definuje gramatiku jazyka. "Klient" sestaví větu ve formě abstraktního syntaktického stromu, v jehož uzlech jsou objekty tříd "TerminalExpression" a "NonterminalExpression" (rekurzivní), poté "Client" inicializuje kontext a zavolá Parse( kontext) operace. Každý uzel typu "NonterminalExpression" definuje operaci analýzy pro každý podvýraz. Pro třídu "NonTerminalExpression" určuje operace Parse základ rekurze. "AbstractExpression" definuje abstraktní operaci Parse společnou pro všechny uzly ve stromu abstraktní syntaxe. "Kontext" obsahuje informace globální pro interpreta.

C#

Zdrojový text v C# pomocí System ; pomocí System.Collections ; jmenný prostor 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 = "čtyři" } } } ; // Výstup: true input . Hodnota = "čtyři" ; výraz . tlumočit ( kontext ); Konzole . WriteLine ( context.result.pop ( ) ) ; _ // Výstup: false input . Hodnota = "44" ; výraz . tlumočit ( kontext ); Konzole . WriteLine ( context.result.pop ( ) ) ; _ } } class Context { public Stack < string > Vysledek = new Stack < string >(); } interface Výraz { void Interpretovat ( Context context ); } abstract class OperatorExpression : Expression { public Expression Left { private get ; nastavit ; } public Expression Right { private get ; nastavit ; } public void Interpret ( Context context ) { Left . tlumočit ( kontext ); řetězec leftValue = kontext . výsledek . pop (); Správně . tlumočit ( kontext ); řetězec rightValue = kontext . výsledek . pop (); DoInterpret ( kontext , leftValue , rightValue ); } chráněný abstrakt void DoInterpret ( kontext kontextu , řetězec leftValue , řetězec rightValue ); } class EqualsExpression : OperatorExpression { protected override void DoInterpret ( kontext kontextu , řetězec leftValue , string rightValue ) { context . výsledek . Push ( leftValue == rightValue ? "true" : "false" ); } } class OrExpression : OperatorExpression { protected override void DoInterpret ( kontext kontextu , řetězec leftValue , string rightValue ) { context . výsledek . Push ( leftValue == "true" || rightValue == "true" ? "true" : "false" ); } } class MyExpression : Expression { public string Value { private get ; nastavit ; } public void Interpretovat ( Context context ) { context . výsledek . Push ( Hodnota ); } } }

Python

Zdrojový kód v Pythonu __doc__ = ''' Systém pro vyhodnocování a manipulaci s booleovskými výrazy. Příklad z Gang of Four - "Design Patterns: Elements of Reusable Object-Oriented Software" ''' z abc import ABCMeta , abstraktní metoda class Context : """ Runtime kontext tlumočníka """ def __init__ ( self , proměnné : dict = {}) -> None : """ Konstruktor. :param variables: slovník shod mezi názvy proměnných a jejich hodnotami " "" self ._variables = variables class ContextException ( Exception ): """ Výjimka vyvolána v případě nesprávné práce s touto třídou """ pass def lookup ( self , name : str ) -> bool : """ Získá hodnotu proměnné podle jejího názvu :param name: název proměnné """ if name in self . _variables : return self . _variables [ name ] raise self . ContextException ( 'Neznámá proměnná {} ' . format ( name )) def assign ( self , name : str , value : bool ) -> None : """ Přiřadí hodnotu proměnné podle jejího názvu :název parametru: název proměnné :hodnota parametru: hodnota proměnné " "" self ._variables [ název ] = hodnota class BooleanExp ( metaclass = ABCMeta ): """ Abstraktní booleovský výraz """ @abstractmethod def vyhodnotit ( self , context : Context ) -> bool : """ Získat výsledek průchodu booleovským výrazem """ class ConstantExp ( BooleanExp ): """ Booleovská konstanta """ def __init__ ( self , hodnota : bool ): """ Konstruktor. :param value: výraz hodnota (pravda nebo nepravda) "" " self ._value = hodnota def ohodnotit ( self , context : Context ): return self . _hodnota class VariableExp ( BooleanExp ): """ Booleovská proměnná (hodnota proměnných je uložena v objektu kontextu interpretu) """ def __init__ ( self , name : str ) -> None : """ Konstruktor. :param jméno: název proměnné " "" self ._name = jméno def vyhodnotit ( self , context : Context ) -> bool : return context . vyhledávání ( self . _name ) class BinaryOperationExp ( BooleanExp , metaclass = ABCMeta ): """ Abstraktní třída pro binární logické operace """ def __init__ ( self , vlevo : BooleanExp , vpravo : BooleanExp ) -> Žádný : """ Konstruktor. :param left: levý operand :param right: pravý operand " " " self ._left = levý self ._right = pravý třída AndExp ( BinaryOperationExp ): """ Konjunkce """ def vyhodnotit ( self , context : Context ) -> bool : return self . _vlevo . hodnotit ( kontext ) a sebe . _správně . hodnotit ( kontext ) třída OrExp ( BinaryOperationExp ): """ Disjunkce """ def vyhodnotit ( self , context : Context ) -> bool : return self . _vlevo . hodnotit ( kontext ) nebo sebe . _správně . hodnotit ( kontext ) třída NotExp ( BooleanExp ): """ Negativní """ def __init__ ( self , operand : BooleanExp ) -> None : """ Konstruktor. :param operand: operand, na který se aplikuje operace """ self . _operand = operand def vyhodnotit ( self , context : Context ) -> bool : return not self . _operand . hodnotit ( kontext ) def execute_test ( context : Context , x : bool , y : bool ) -> None : """ Funkce pro provádění testů na našem """ kontextovém interpretu . přiřadit ( 'x' , x ) kontext . přiřadit ( 'y' , y ) výraz = OrExp ( # (True a x) nebo (y a (ne x)) AndExp ( ConstantExp ( True ), VariableExp ( 'x' )), AndExp ( VariableExp ( 'y' ) , NotExp ( VariableExp ( 'x' ))) ) tisk ( výraz . vyhodnocení ( kontext )) if __name__ == '__main__' : print ( 'OUTPUT:' ) context = Context () execute_test ( context , True , False ) execute_test ( context , False , True ) execute_test ( context , False , False ) ''' VÝSTUP: Pravda Pravda Nepravda '''

PHP

Zdrojový kód PHP <?php /** * Příklad vzoru tlumočníka pomocí kompozice */ abstract class Expression { private static $_count = 0 ; private $_key = null ; veřejná abstraktní funkce interpret ( InterpreterContext $context ); public function getKey () { if ( ! isset ( $this -> _key ) ) { self :: $_count ++ ; $this -> _key = self :: $_count ; } return $this -> _key ; } } class LiteralExpression rozšiřuje výraz { private $_value = null ; public function __construct ( $value ) { $this -> _value = $hodnota ; } public function interpret ( InterpreterContext $context ) { $context -> nahradit ( $this , $this -> _value ); } } class VariableExpression rozšiřuje výraz { private $_name = null ; private $_val = null ; public function __construct ( $name , $val = null ) { $this -> _name = $name ; $this -> _val = $val ; } public function interpret ( InterpreterContext $context ) { if ( ! is_null ( $this -> _val ) ) $context -> nahradit ( $this , $this -> _val ); } public function setValue ( $hodnota ) { $this -> _val = $hodnota ; } public function getKey () { return $this -> _name ; } } abstraktní třída OperatorExpression rozšiřuje výraz { protected $leftoperand = null ; protected $rightoperand = null ; public function __construct ( Výraz $levýoperand , Výraz $pravýoperand ) { $this -> levýoperand = $levýoperand ; $this -> pravýoperand = $pravýoperand ; } public function interpret ( InterpreterContext $context ) { $this -> leftoperand -> interpret ( $context ); $this -> pravý operand -> interpretovat ( $kontext ); $resultleft = $kontext -> vyhledávání ( $this -> levýoperand ); $resultright = $kontext -> vyhledávání ( $this -> pravý operand ); $this -> doInterpret ( $context , $ resultleft , $resultright ); } chráněná abstraktní funkce doInterpret ( InterpreterContext $context , $ resultleft , $resultright ); } class EqualsExpression rozšiřuje OperatorExpression { chráněná funkce doInterpret ( InterpreterContext $context , $ resultleft , $resultright ) { $context -> nahradit ( $this , $ resultleft == $resultright ); } } class BooleanOrExpression rozšiřuje OperatorExpression { chráněná funkce doInterpret ( InterpreterContext $context , $ resultleft , $resultright ) { $kontext -> nahradit ( $this , $ resultleft || $resultright ); } } class BooleanAndExpression rozšiřuje OperatorExpression { chráněná funkce doInterpret ( InterpreterContext $context , $ resultleft , $resultright ) { $context -> nahradit ( $this , $ resultleft && $resultright ); } } class InterpreterContext { private $_expressionstore = pole (); public function replacement ( Expression $exp , $value ) { $this -> _expressionstore [ $exp -> getKey ()] = $value ; } public function lookup ( Expression $exp ) { return $this -> _expressionstore [ $exp -> getKey ()]; } } $context = new InterpreterContext (); $input = new VariableExpression ( 'vstup' ); $statement = new BooleanOrExpression ( new EqualsExpression ( $input , new LiteralExpression ( "čtyři" ) ), nový EqualsExpression ( $input , nový LiteralExpression ( "4" ) ) ); foreach ( pole ( "čtyři" , "4" , "52" ) ​​​​jako $hodnota ) { $vstup -> setValue ( $hodnota ); print " { $hodnota } :<br>" ; $statement -> interpretovat ( $kontext ); tisk $context -> lookup ( $statement ) ? "Splňuje<br><br>" : "Neodpovídá<br><br>" ; } ?>

Viz také