Behavioral — Davranışsal Desenler

Interpreter

Yorumlayıcı Deseni

Amaç: Basit bir dilin gramerini sınıflarla temsil etmek ve bu dilde yazılmış ifadeleri yorumlayıp değerlendirmek.

1

Basit Anlatım

Teknik terim yok — günlük hayattan bir benzetme

Bir müzisyen nota kâğıdına bakıp şarkıyı çalar. Notalar aslında küçük bir dildir: her sembolün bir anlamı var (do, re, mi, uzun, kısa, sus). Müzisyen her sembolü tanır ve bir araya geldiklerinde ne anlama geldiğini "yorumlar".

Tarif kartı

Bir yemek tarifinde "2 su bardağı un + 1 yumurta, sonra 10 dakika karıştır" yazar. Bu da küçük bir dildir. Her ifade daha küçük ifadelerden oluşur: "2 su bardağı un" bir malzeme, "+" birleştirme, "10 dakika karıştır" bir işlem.

Yorumlayıcı, cümleyi parçalarına ayırır ve her parçayı kendi kuralına göre değerlendirir. Büyük ifadenin anlamı, küçük ifadelerin anlamlarının birleşimidir.

Interpreter şunu der: "Küçük bir dilin her kuralını bir yapı taşı yap; taşları birleştirerek cümleleri anla."
2

Teknik Anlamı

Bir yazılımcının bakış açısıyla

Interpreter, bir dilin gramerindeki her kuralı bir sınıf olarak temsil eder. İfadeler bu sınıflardan oluşan bir soyut sözdizimi ağacı (AST) olarak kurulur ve Interpret(context) metodu ağaç üzerinde özyinelemeli olarak çalışır. Yapısal olarak Composite deseninin özel bir uygulamasıdır.

Katılımcılar

Kullanım alanları

Avantajlar

Dezavantajlar

Interpreter genellikle ifadeyi çalıştırma kısmıyla ilgilenir. Metni ağaca dönüştürme (parsing) ayrı bir konudur; aşağıdaki örnekte ağacı elle kuracağız.
3

C# ile Uygulama

Adım adım, çalışan kod örneği

Senaryo: Bir indirim kural motoru. Kurallar şu şekilde tanımlanabilsin: "Toplam > 500 VE (Üye MI VEYA Kupon VAR MI)".

Adım 1 Context ve ifade arayüzü

public class Context
{
    private readonly Dictionary<string, object> _values = new();

    public void Set(string name, object value) => _values[name] = value;
    public object Get(string name) => _values[name];
}

public interface IExpression
{
    bool Interpret(Context ctx);
    string Describe();
}

Adım 2 Terminal ifadeler: gramerin yaprakları

public class IsTrue : IExpression
{
    private readonly string _name;
    public IsTrue(string name) => _name = name;

    public bool Interpret(Context ctx) => (bool)ctx.Get(_name);
    public string Describe() => _name;
}

public class GreaterThan : IExpression
{
    private readonly string _name;
    private readonly decimal _limit;
    public GreaterThan(string name, decimal limit) { _name = name; _limit = limit; }

    public bool Interpret(Context ctx) => (decimal)ctx.Get(_name) > _limit;
    public string Describe() => $"{_name} > {_limit}";
}

Adım 3 Nonterminal ifadeler: diğer ifadeleri birleştiren kurallar

Her biri alt ifadelerini yorumlatır ve sonucu birleştirir.

public class And : IExpression
{
    private readonly IExpression _left, _right;
    public And(IExpression left, IExpression right) { _left = left; _right = right; }

    public bool Interpret(Context ctx) => _left.Interpret(ctx) && _right.Interpret(ctx);
    public string Describe() => $"({_left.Describe()} VE {_right.Describe()})";
}

public class Or : IExpression
{
    private readonly IExpression _left, _right;
    public Or(IExpression left, IExpression right) { _left = left; _right = right; }

    public bool Interpret(Context ctx) => _left.Interpret(ctx) || _right.Interpret(ctx);
    public string Describe() => $"({_left.Describe()} VEYA {_right.Describe()})";
}

public class Not : IExpression
{
    private readonly IExpression _inner;
    public Not(IExpression inner) => _inner = inner;

    public bool Interpret(Context ctx) => !_inner.Interpret(ctx);
    public string Describe() => $"DEĞİL {_inner.Describe()}";
}

Adım 4 Kullanım

Tüm parçaları bir araya getiren istemci (client) kodu:

// Kural: Toplam > 500 VE (Üye VEYA Kupon) VE DEĞİL Kara listede
IExpression rule =
    new And(
        new And(new GreaterThan("Toplam", 500),
                new Or(new IsTrue("Üye"), new IsTrue("Kupon"))),
        new Not(new IsTrue("KaraListe")));

Console.WriteLine($"Kural: {rule.Describe()}\n");

var customers = new (string Name, decimal Total, bool Member, bool Coupon, bool Banned)[]
{
    ("Ahmet", 750, true, false, false),
    ("Zeynep", 300, true, true, false),
    ("Burak", 900, false, true, false),
    ("Deniz", 1200, true, false, true),
};

foreach (var c in customers)
{
    var ctx = new Context();
    ctx.Set("Toplam", c.Total);
    ctx.Set("Üye", c.Member);
    ctx.Set("Kupon", c.Coupon);
    ctx.Set("KaraListe", c.Banned);
    Console.WriteLine($"{c.Name,-7} -> indirim {(rule.Interpret(ctx) ? "UYGULANIR" : "yok")}");
}

Konsol çıktısı

Kural: ((Toplam > 500 VE (Üye VEYA Kupon)) VE DEĞİL KaraListe)

Ahmet   -> indirim UYGULANIR
Zeynep  -> indirim yok
Burak   -> indirim UYGULANIR
Deniz   -> indirim yok

Kodda dikkat edilmesi gerekenler

Özetle: Interpreter, basit bir dilin her kuralını bir sınıf yapar ve ifadeleri bu sınıflardan oluşan bir ağaç üzerinde değerlendirir.
← Ana sayfaya dön