Tulkki (suunnittelukuvio)

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 5. huhtikuuta 2017 tarkistetusta versiosta . tarkastukset vaativat 12 muokkausta .
Tulkki
tulkki
Tyyppi käyttäytymiseen
Tarkoitus ratkaisee usein kohdattavan ongelman, joka voi muuttua
Kuvattu suunnittelukuvioissa Joo

Tulkki on käyttäytymismalli  , joka ratkaisee usein kohtaaman , mutta muuttuvan tehtävän. Tunnetaan myös nimellä Little (Small) Language

Ongelma

Siellä on usein esiintyvä tehtävä, joka voi muuttua.

Ratkaisu

Luo tulkki, joka ratkaisee tämän ongelman.

Edut

Kielioppi on helppo laajentaa ja muuttaa, abstraktin syntaksipuun solmuja kuvaavien luokkien toteutukset ovat samanlaisia ​​(helposti koodattuja). Voit helposti muuttaa tapaa, jolla lausekkeet arvioidaan.

Haitat

Kieliopin ylläpitäminen suurella määrällä sääntöjä on vaikeaa.

Esimerkki

Merkkijonojen etsiminen kuvion mukaan voidaan ratkaista luomalla tulkki, joka määrittelee kielen kieliopin. "Client" rakentaa lauseen abstraktin syntaksipuun muodossa, jonka solmuissa on objekteja luokista "TerminalExpression" ja "NonterminalExpression" (rekursiivinen), sitten "Client" alustaa kontekstin ja kutsuu Parse( konteksti) -toiminto. Jokainen "NonterminalExpression"-tyypin solmu määrittää jäsennystoiminnon kullekin alilausekkeelle. "NonTerminalExpression"-luokassa jäsennystoiminto määrittää rekursion perustan. "AbstractExpression" määrittää abstraktin jäsennystoiminnon, joka on yhteinen kaikille abstraktin syntaksipuun solmuille. "Konteksti" sisältää tulkin globaalia tietoa.

C#

Lähdeteksti C# käyttäen System ; käyttämällä System.Collections -ohjelmaa ; nimiavaruus DoFactory.GangOfFour.Interpreter.Structural { class Program { static void Main () { var konteksti = new Context (); var input = uusi MyExpression (); var lauseke = uusi OrExpression { Vasen = uusi EqualsExpression { Vasen = syöte , Oikea = uusi OmaLauseke { Arvo = "4" } }, Oikea = uusi EqualsExpression { Vasen = input , Oikea = uusi Omalauseke { Arvo = "neljä" } } } ; // Tulostus: true input . Arvo = "neljä" ; ilmaisua . tulkita ( konteksti ); konsoli . WriteLine ( konteksti.tulos.pop ( ) ) ; _ // Lähtö: väärä syöttö . Arvo = "44" ; ilmaisua . tulkita ( konteksti ); konsoli . WriteLine ( konteksti.tulos.pop ( ) ) ; _ } } class Konteksti { public Pino < merkkijono > Tulos = new Pino < merkkijono >(); } käyttöliittymä Lauseke { void Tulkita ( kontekstikonteksti ) ; } abstrakti luokka OperatorExpression : Lauseke { public Expression Left { private get ; asettaa ; } public Expression Right { private get ; asettaa ; } public void Tulkita ( kontekstikonteksti ) { Vasen . _ tulkita ( konteksti ); merkkijono leftValue = konteksti . tulos . pop (); Oikein . tulkita ( konteksti ); string rightValue = konteksti . tulos . pop (); DoIninterpret ( konteksti , leftValue , rightValue ); } suojattu abstrakti void DoInterpret ( kontekstikonteksti , merkkijono leftValue , merkkijono rightValue ) ; } class EqualsExpression : OperatorExpression { suojattu ohitus void DoInterpret ( kontekstikonteksti , merkkijono leftValue , string rightValue ) { konteksti . _ tulos . Push ( leftValue == rightValue ? "true" : "false" ); } } class OrExpression : OperatorExpression { suojattu ohitus void DoInterpret ( kontekstikonteksti , merkkijono leftValue , string rightValue ) { konteksti . _ tulos . Push ( leftValue == "tosi" || rightValue == "tosi" ? "tosi" : "false" ); } } class MyExpression : Lauseke { public string Arvo { private get ; asettaa ; } public void Tulkita ( kontekstikonteksti ) { konteksti . _ tulos . Työnnä ( arvo ); } } }

Python

Lähdekoodi Pythonissa __doc__ = ''' Järjestelmä loogisten lausekkeiden arviointiin ja käsittelyyn. Esimerkki Gang of Fourista - "Design Patterns: Elements of Reusable Object Oriented Software" ''' abc importista ABCMeta , abstrakti menetelmä luokan konteksti : """ Tulkin "" " ajonaikainen konteksti def __init__ ( itse , muuttujat : dict = {}) -> Ei mitään : """ Rakentaja. :param variables: sanakirja vastaavuuksista muuttujien nimien ja niiden arvojen välillä " "" itse ._variables = muuttujat luokka ContextException ( Poikkeus ): """ Poikkeus tehdään virheellisen työn yhteydessä tämän luokan """ passilla def lookup ( itse , nimi : str ) -> bool : """ Hakee muuttujan arvon sen nimen mukaan :param nimi: muuttujan nimi """ jos nimi itsessä . _variables : palauttaa itsensä . _muuttujat [ nimi ] nostavat itsensä . ContextException ( ' Tuntematon muuttuja {} ' . muoto ( nimi )) def assign ( itse , nimi : str , arvo : bool ) -> Ei mitään : """ Määrittää muuttujalle arvon sen nimen perusteella :param nimi: muuttujan nimi :param arvo: muuttujan arvo " "" itse ._variables [ nimi ] = arvo luokka BooleanExp ( metaluokka = ABCMeta ): """ Abstrakti boolen lauseke """ @abstractmethod def arvo _ _ _ _ _ _ _ _ _ _ _ _ _ _ luokka ConstantExp ( BooleanExp ): """ Boolen vakio """ def __init__ ( itse , arvo : bool ): """ Rakentaja. :param arvo: lausekkeen arvo (tosi tai epätosi) "" " itse ._value = arvo def arvioida ( itse , konteksti : konteksti ): palauttaa itse . _arvo luokka VariableExp ( BooleanExp ): """ Boolen muuttuja (muuttujien arvot tallennetaan tulkin kontekstiobjektiin) """ def __init__ ( itse , nimi : str ) -> Ei mitään : """ Rakentaja. :param nimi: muuttujan nimi " "" itse ._name = nimi def arvioida ( itse , konteksti : konteksti ) -> bool : palauttaa kontekstin . haku ( itse . _nimi ) luokka BinaryOperationExp ( BooleanExp , metaclass = ABCMeta ): """ Abstrakti luokka binaarisille loogisille operaatioille """ def __init__ ( itse , vasen : BooleanExp , oikea : BooleanExp ) -> Ei mitään : """ Rakentaja. :param vasen: vasen operandi :param right: oikea operandi " " " itse ._left = vasen itse ._right = oikea luokka AndExp ( BinaryOperationExp ): """ Konjunktio """ def arvioida ( itse , konteksti : konteksti ) -> bool : palauttaa itsensä . _vasen . arvioida ( kontekstia ) ja itseään . _oikein . arvioida ( konteksti ) luokka OrExp ( BinaryOperationExp ): """ Disjunktio """ def arvioida ( itse , konteksti : konteksti ) -> bool : palauttaa itsensä . _vasen . arvioida ( konteksti ) tai itseään . _oikein . arvioida ( konteksti ) luokka NotExp ( BooleanExp ): """ Negatiivinen """ def __init__ ( itse , operandi : BooleanExp ) -> Ei mitään : """ Rakentaja. :param operandi: operandi, johon """ -toimintoa sovelletaan itse _operand = operandi def arvioida ( itse , konteksti : konteksti ) -> bool : palauttaa ei itse . _operandi . arvioida ( konteksti ) def execute_test ( konteksti : konteksti , x : bool , y : bool ) -> Ei mitään : """ Toiminto, joka suorittaa testejä """ -kontekstitulkkillamme . määrittää ( 'x' , x ) konteksti . assign ( 'y' , y ) lauseke = OrLaus ( # (tosi ja x) tai (y ja (ei x)) AndExp ( VakioLaus ( True ), VariableExp ( 'x' )), AndExp ( MuuttujaLaus ( 'y' ) , NotExp ( VariableExp ( 'x' ))) ) print ( lauseke . arvioida ( konteksti )) if __name__ == '__main__' : print ( 'OUTPUT:' ) konteksti = Konteksti () execute_test ( konteksti , tosi , epätosi ) execute_test ( konteksti , epätosi , tosi ) execute_test ( konteksti , epätosi , epätosi ) ''' TULOS: tosi tosi Väärin '''

PHP

PHP lähdekoodi <?php /** * Esimerkki tulkin kuviosta koostumuksella */ abstrakti luokka Lauseke { yksityinen staattinen $_count = 0 ; yksityinen $_avain = null ; julkinen abstrakti funktio tulkita ( InterpreterContext $context ); public function getKey () { if ( ! isset ( $this -> _key ) ) { self :: $_count ++ ; $this -> _key = itse :: $_count ; } return $this -> _key ; } } class LiteralExpression laajentaa lausekkeen { yksityinen $_arvo = null ; julkinen funktio __konstrukti ( $arvo ) { $this -> _value = $arvo ; } public function interpret ( InterpreterContext $context ) { $context -> korvaa ( $this , $this -> _value ); } } class VariableExpression laajentaa lausekkeen { yksityinen $_nimi = null ; yksityinen $_val = null ; julkinen funktio __konstrukti ( $nimi , $val = null ) { $this -> _name = $nimi ; $this -> _val = $val ; } julkinen funktio tulkita ( InterpreterContext $konteksti ) { if ( ! is_null ( $this -> _val ) ) $context -> korvaa ( $this , $this -> _val ); } julkinen funktio setValue ( $arvo ) { $this -> _val = $arvo ; } public function getKey () { return $this -> _name ; } } abstrakti luokka OperatorExpression laajentaa lausekkeen { suojattu $leftoperand = null ; suojattu $rightoperand = null ; public function __construct ( Lauseke $vasenoperand , Lauseke $oikeaoperand ) { $this -> leftoperand = $vasenoperand ; $this -> rightoperand = $rightoperand ; } julkinen funktio tulkita ( InterpreterContext $context ) { $this -> leftoperand -> interpret ( $context ); $this -> rightoperand -> tulkita ( $context ); $resultleft = $konteksti -> haku ( $this -> leftoperand ); $resultright = $konteksti -> haku ( $this -> rightoperand ); $this -> doInterpret ( $context , $resultleft , $resultright ); } suojattu abstrakti funktio doInterpret ( InterpreterContext $context , $resultleft , $resultright ); } class EqualsExpression laajentaa OperatorExpression { suojattu toiminto doInterpret ( InterpreterContext $context , $resultleft , $resultright ) { $konteksti -> korvaa ( $this , $resultleft == $resultright ); } } class BooleanOrExpression laajentaa OperatorExpression { suojattu toiminto doInterpret ( InterpreterContext $context , $resultleft , $resultright ) { $konteksti -> korvaa ( $this , $resultleft || $resultright ); } } class BooleanAndExpression laajentaa OperatorExpression { suojattu toiminto doInterpret ( InterpreterContext $context , $resultleft , $resultright ) { $context -> korvaa ( $this , $resultleft && $resultright ); } } class InterpreterContext { yksityinen $_expressionstore = array (); julkinen funktio korvaa ( Lauseke $exp , $arvo ) { $this -> _expressionstore [ $exp -> getKey ()] = $arvo ; } julkinen funktiohaku ( Lauseke $exp ) { return $this -> _expressionstore [ $exp -> getKey ( )]; } } $konteksti = uusi tulkkikonteksti (); $syöte = new VariableExpression ( 'input' ); $lauseke = uusi BooleanOrExpression ( uusi EqualsExpression ( $syöttö , uusi LiteralExpression ( "neljä" ) ), uusi EqualsExpression ( $syöte , uusi LiteralExpression ( "4" ) ) ); foreach ( array ( "neljä" , "4" , "52" ) ​​as $value ) { $input -> setValue ( $arvo ); tulosta " { $arvo } :<br>" ; $lausunto -> tulkita ( $konteksti ); tulosta $context -> lookup ( $lauseke ) ? "Meets<br><br>" : "Ei vastaa<br><br>" ; } ?>

Katso myös