Tolmács (tervezési minta)
Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2017. április 5-én felülvizsgált
verziótól ; az ellenőrzések 12 szerkesztést igényelnek .
Tolmács |
---|
tolmács |
Típusú |
viselkedési |
Célja |
megold egy gyakran előforduló, változékony problémát |
Leírása: Tervezési minták |
Igen |
Az interpreter egy viselkedési tervezési minta , amely egy gyakran előforduló, de változékony feladatot old meg. Más néven Little (Small) Language
Probléma
Van egy gyakran előforduló, változékony feladat.
Megoldás
Hozzon létre egy tolmácsot, amely megoldja ezt a problémát.
Előnyök
A nyelvtan könnyen bővíthetővé, módosíthatóvá válik, az absztrakt szintaxisfa csomópontjait leíró osztályok megvalósításai hasonlóak (könnyen kódolhatók). Könnyen módosíthatja a kifejezések kiértékelésének módját.
Hátrányok
A sok szabályt tartalmazó nyelvtan fenntartása nehéz.
Példa
A karakterláncok minta szerinti keresésének feladatát a nyelv grammatikáját definiáló interpreter létrehozásával lehet megoldani. A "Kliens" egy absztrakt szintaktikai fa formájában épít fel egy mondatot, amelynek csomópontjaiban "TerminalExpression" és "NonterminalExpression" (rekurzív) osztályú objektumok találhatók, majd a "Client" inicializálja a kontextust és meghívja a Parse( Kontextus) művelet. Minden "NonterminalExpression" típusú csomópont meghatároz egy elemzési műveletet minden egyes részkifejezéshez. A "NonTerminalExpression" osztály esetében a Parse művelet határozza meg a rekurzió alapját. Az "AbstractExpression" meghatározza az absztrakt elemzési műveletet, amely az absztrakt szintaxisfa összes csomópontjára jellemző. A "Kontextus" globális információkat tartalmaz a tolmács számára.
Forrásszöveg C# nyelven
a rendszer használatával ;
a System.Collections használatával ;
névtér DoFactory.GangOfFour.Interpreter.Structural
{
class Program
{
static void Main ()
{
var context = new Context ();
var input = new MyExpression ();
var kifejezés = new OrExpression
{
Left = new EqualsExpression
{
Left = input ,
Right = new MyExpression { Value = "4" }
},
Right = new EqualsExpression
{
Left = input ,
Right = new MyExpression { Érték = "négy" }
}
} ;
// Kimenet: true
input . Érték = "négy" ;
kifejezés . értelmezni ( kontextus );
Konzol . WriteLine ( context.result.pop ( ) ) ; _
// Kimenet: false
input . Érték = "44" ;
kifejezés . értelmezni ( kontextus );
Konzol . WriteLine ( context.result.pop ( ) ) ; _ } }
class Kontextus
{
public Stack < string > Eredmény = new Verem < string >();
}
interface Kifejezés
{
void Interpret ( kontextus ) ;
}
absztrakt osztály OperatorExpression : Kifejezés
{
public Expression Left { private get ; készlet ; }
public Expression Right { private get ; készlet ; }
public void Értelmezés ( Környezetkörnyezet ) { Balra . _ értelmezni ( kontextus ); string leftValue = kontextus . eredmény . pop ();
Igaz . értelmezni ( kontextus );
string rightValue = kontextus . eredmény . pop ();
DoInterpret ( kontextus , leftValue , rightValue );
}
védett absztrakt void DoInterpret ( Kontextus kontextus , string leftValue , string rightValue );
}
class EqualsExpression : OperatorExpression
{
protected override void DoInterpret ( Kontextus kontextus , string leftValue , string rightValue )
{
context . eredmény . Push ( leftValue == rightValue ? "true" : "false" );
}
}
class OrExpression : OperatorExpression
{
protected override void DoInterpret ( kontextus kontextus , string leftValue , string rightValue )
{
kontextus . eredmény . Push ( leftValue == "igaz" || rightValue == "igaz" ? "igaz" : "hamis" );
}
}
class MyExpression : Kifejezés
{
public string Érték { private get ; készlet ; }
public void Interpret ( Context context )
{
context . eredmény . Push ( Érték );
}
}
}
Forráskód Pythonban
__doc__ = '''
Logikai kifejezések kiértékelésére és kezelésére szolgáló rendszer. Példa a
Gang of Four-ból - "Tervezési minták: Az újrafelhasználható objektum-orientált szoftver elemei"
'''
abc importból ABCMeta , abstractmethod _
osztály Kontextus :
""" A
""" értelmező futási környezete
def __init__ ( self , változók : dict = {}) -> Nincs :
"""
Konstruktor.
:param változók: a változónevek és azok értékei közötti egyezések szótára
" ""
self ._variables = változók
osztály KontextusKivétel ( Kivétel ):
"""
Kivételt adunk, ha helytelen munkát végeztek ezzel a
"""
osztályzattal
def lookup ( self , name : str ) -> bool :
"""
Lekéri a változó értékét a neve alapján
:param név: változó neve
"""
, ha a név önmagában . _variables : önmagát adja vissza . _variables [ név ] önmagát emeli . ContextException ( 'Ismeretlen változó {} ' . formátum ( név ))
def assign ( self , name : str , value : bool ) -> None :
"""
Értéket rendel egy változóhoz a neve alapján
:param name: változó neve
:param value: változó értéke
" ""
self ._variables [ név ] = érték
osztály BooleanExp ( metaclass = ABCMeta ):
"""
Absztrakt logikai kifejezés
"""
@abstractmethod
def arvo _ _ _ _ _ _ _ _ _ _
_
_
_
_
osztály ConstantExp ( BooleanExp ):
"""
Logikai konstans
"""
def __init__ ( self , value : bool ):
"""
Konstruktor.
:param value: kifejezés értéke (igaz vagy hamis)
""
" self ._value = érték
def értékel ( self , kontextus : Context ):
return self . _érték
osztály VariableExp ( BooleanExp ):
"""
Logikai változó (a változók értéke az értelmező környezeti objektumban van tárolva)
"""
def __init__ ( self , name : str ) -> None :
"""
Konstruktor.
:param név: változó neve
" ""
self ._name = név
def értékel ( self , kontextus : kontextus ) -> bool :
kontextus visszaadása . keresés ( self . _name )
osztály BinaryOperationExp ( BooleanExp , metaclass = ABCMeta ):
"""
Absztrakt osztály bináris logikai műveletekhez
"""
def __init__ ( self , balra : BooleanExp , jobbra : BooleanExp ) -> None :
"""
Konstruktor.
:param left: left operandus
:param right: right operandus
" "
" self ._left = left self ._right = right
osztály AndExp ( BinaryOperationExp ):
"""
Konjunkció
"""
def értékel ( self , kontextus : kontextus ) -> bool :
önmagát adja vissza . _balra . értékeli ( kontextus ) és önmagát . _jobbra . értékelni ( kontextus )
osztály OrExp ( BinaryOperationExp ):
"""
Disjunkció
"""
def értékel ( self , kontextus : kontextus ) -> bool :
önmagát adja vissza . _balra . értékeli ( kontextus ) vagy önmagát . _jobbra . értékelni ( kontextus )
osztály NotExp ( BooleanExp ):
"""
Negatív
"""
def __init__ ( self , operandus : BooleanExp ) -> None :
"""
Konstruktor.
:param operandus: operandus, amelyre a
""" művelet
önállóan kerül alkalmazásra _operand = operandus
def értékel ( self , kontextus : kontextus ) -> bool :
return not self . _operand . értékelni ( kontextus )
def execute_test ( context : Context , x : bool , y : bool ) -> None :
""" A
""" kontextus értelmezőnk tesztelésére szolgáló függvény
. hozzárendelni ( 'x' , x ) kontextust . hozzárendel ( 'y' , y ) kifejezés = OrExp ( # (Igaz és x) vagy (y és (nem x)) AndExp ( ConstantExp ( True ), VariableExp ( 'x' )), AndExp ( VariableExp ( 'y' )) , NotExp ( VariableExp ( 'x' ))) ) print ( kifejezés . értékel ( kontextus ))
if __name__ == '__main__' :
print ( 'OUTPUT:' )
context = Context ()
execute_test ( kontextus , igaz , hamis )
execute_test ( kontextus , hamis , igaz )
execute_test ( kontextus , hamis , hamis )
'''
KIMENET:
Igaz
Igaz
Hamis
'''
PHP forráskód
<?php
/**
* Példa értelmező mintára összetétel használatával
*/
abstract class Kifejezés {
privát statikus $_count = 0 ;
privát $_kulcs = null ;
public absztrakt függvény értelmez ( InterpreterContext $context );
public function getKey () {
if ( ! isset ( $this -> _key ) ) {
self :: $_count ++ ;
$this -> _key = self :: $_count ;
}
return $this -> _key ;
}
}
class LiteralExpression kiterjeszti a kifejezést {
privát $_érték = null ;
public function __construct ( $érték ) {
$this -> _value = $érték ;
}
public function interpret ( InterpreterContext $context ) {
$context -> csere ( $this , $this -> _value );
}
}
class VariableExpression kiterjeszti a kifejezést {
privát $_név = 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 -> csere ( $this , $this -> _val );
}
public function setValue ( $érték ) {
$this -> _val = $érték ;
}
public function getKey () {
return $this -> _name ;
}
}
abstract class OperatorExpression extends kifejezés {
védett $leftoperand = null ;
védett $rightoperand = null ;
public function __construct ( Kifejezés $baloperand , Kifejezés $jobboperand ) {
$this -> leftoperand = $baloperand ;
$this -> rightoperand = $jobboperandus ;
}
public function interpret ( InterpreterContext $context ) {
$this -> leftoperand -> interpret ( $context );
$this -> rightoperand -> interpret ( $context );
$resultleft = $kontextus -> keresés ( $this -> leftoperand );
$resultright = $kontextus -> keresés ( $this -> rightoperand );
$this -> doInterpret ( $context , $ resultleft , $resultright );
}
védett absztrakt függvény doInterpret ( InterpreterContext $context , $ resultleft , $resultright );
}
class EqualsExpression kiterjeszti az OperatorExpression {
protected function doInterpret ( InterpreterContext $context , $ resultleft , $resultright ) {
$kontextus -> csere ( $this , $ resultleft == $resultright );
}
}
class BooleanOrExpression kiterjeszti az OperatorExpression {
protected function doInterpret ( InterpreterContext $context , $ resultleft , $resultright ) {
$kontextus -> csere ( $this , $ resultleft || $resultright );
}
}
class BooleanAndExpression kiterjeszti az OperatorExpression {
protected function doInterpret ( InterpreterContext $context , $ resultleft , $resultright ) {
$context -> csere ( $this , $ resultleft && $resultright );
}
}
class InterpreterContext {
private $_expressionstore = tömb ();
public function csere ( Kifejezés $exp , $érték ) {
$this -> _expressionstore [ $exp -> getKey ()] = $érték ;
}
public function lookup ( $exp kifejezés ) { return $this -> _expressionstore [ $exp -> getKey ()]; }
}
$kontextus = new InterpreterContext ();
$input = new VariableExpression ( 'input' );
$statement = new BooleanOrExpression (
new EqualsExpression ( $input , new LiteralExpression ( "négy" ) ),
new EqualsExpression ( $input , new LiteralExpression ( "4" ) )
);
foreach ( array ( "négy" , "4" , "52" ) as $value ) {
$input -> setValue ( $value );
print " { $value } :<br>" ;
$nyilatkozat -> interpret ( $kontextus );
nyomtatás $context -> lookup ( $statement )
? "Meets<br><br>"
: "Nem egyezik<br><br>" ;
}
?>
Lásd még