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