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.
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 );
}
}
}
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
'''
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é