Menu
Coddy logo textTech

Şablon Metot Kalıbı

Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 94 / 107.

Şablon Yöntemi deseni, bir algoritmanın iskeletini temel türde tanımlar ve alt türlerin genel yapıyı değiştirmeden belirli adımları geçersiz kılmasına olanak tanır. Decorator, nesneleri sarmalayarak davranış eklerken Şablon Yöntemi algoritmanın akışını kontrol eder ve tek tek adımların özelleştirilmesine izin verir.

Go'da kalıtım olmadığı için bu kalıbı, yapı gömme özelliğini arayüzlerle birleştirerek uygularız. "template" yapısı algoritmanın yapısını tanımlar ve özelleştirilebilen yöntemleri çağırır:

type DataProcessor interface {
    ReadData() string
    ProcessData(data string) string
    SaveData(result string) string
}

type BaseProcessor struct {
    Impl DataProcessor
}

func (b *BaseProcessor) Execute() string {
    data := b.Impl.ReadData()
    result := b.Impl.ProcessData(data)
    return b.Impl.SaveData(result)
}

Somut uygulamalar, algoritma akışı değişmeden her adımın kendi sürümünü sağlar:

type CSVProcessor struct{}

func (c CSVProcessor) ReadData() string       { return "csv-data" }
func (c CSVProcessor) ProcessData(d string) string { return "processed-" + d }
func (c CSVProcessor) SaveData(r string) string    { return "Saved: " + r }

type JSONProcessor struct{}

func (j JSONProcessor) ReadData() string       { return "json-data" }
func (j JSONProcessor) ProcessData(d string) string { return "parsed-" + d }
func (j JSONProcessor) SaveData(r string) string    { return "Stored: " + r }

Şablon methodu Execute, adımları sabit bir sırayla düzenler:

csvProc := &BaseProcessor{Impl: CSVProcessor{}}
fmt.Println(csvProc.Execute())  // Kaydedildi: processed-csv-data

jsonProc := &BaseProcessor{Impl: JSONProcessor{}}
fmt.Println(jsonProc.Execute()) // Saklandı: parsed-json-data

Template Method, aynı yapıyı paylaşan ancak belirli adımlarda farklılık gösteren algoritmalara sahip olduğunuzda idealdir; örneğin veri içe/dışa aktarma işlem hatları, rapor oluşturucular veya test çerçeveleri.

challenge icon

Görev

Kolay

Şablon Method kalıbını kullanarak bir rapor oluşturma sistemi geliştirelim! Farklı rapor türlerinin aynı oluşturma sürecini izlediği; verileri topladığı, biçimlendirdiği ve sonucu çıktı olarak verdiği, ancak her rapor türünün bu adımları farklı şekilde özelleştirdiği bir çerçeve oluşturacaksın.

Kodunu üç dosya arasında düzenleyeceksin:

  • report.go: Arayüzünü ve rapor oluşturma algoritmasını yöneten temel işlemciyi tanımla.

    Rapor oluşturma adımlarını temsil eden üç metoda sahip bir ReportGenerator arayüzü oluştur:

    • GatherData() string: rapor için ham verileri alır
    • FormatData(data string) string: verileri raporun biçimine dönüştürür
    • OutputReport(formatted string) string: nihai çıktı mesajını oluşturur

    Bir ReportProcessor uygulamasını tutan bir ReportGenerator yapısı oluştur. Üç adımı sırayla (topla, biçimlendir, ardından çıktı olarak ver) gerçekleştiren ve nihai sonucu döndüren bir Generate() string metodu ekle.

  • generators.go: Her adımı özelleştiren somut rapor oluşturucuları uygula.

    İki rapor türü oluştur:

    • SalesReport, bir Region alanına (string) sahip
      • GatherData(), sales-data-[region] değerini döndürür
      • FormatData(data), SALES REPORT: [data] değerini döndürür
      • OutputReport(formatted), Printed: [formatted] değerini döndürür
    • InventoryReport, bir Warehouse alanına (string) sahip
      • GatherData(), inventory-[warehouse] değerini döndürür
      • FormatData(data), *** [data] *** değerini döndürür
      • OutputReport(formatted), Exported: [formatted] değerini döndürür
  • main.go: Aynı algoritma yapısının uygulamaya bağlı olarak nasıl farklı sonuçlar ürettiğini göster.

    Rapor türünü (sales veya inventory) ve yapılandırma değerini (sales için bölge, inventory için depo) oku. Uygun oluşturucuyu oluştur, onu bir ReportProcessor içine yerleştir, Generate() metodunu çağır ve sonucu yazdır.

Aşağıdaki girdiler sağlanacaktır:

  • 1. satır: Rapor türü (sales veya inventory)
  • 2. satır: Yapılandırma değeri (bölge adı veya depo adı)

Örneğin, şu verildiğinde:

sales
North

Çıktın şu olmalıdır:

Printed: SALES REPORT: sales-data-North

Ve şu verildiğinde:

inventory
MainHub

Çıktın şu olmalıdır:

Exported: *** inventory-MainHub ***

Ve şu verildiğinde:

sales
West

Çıktın şu olmalıdır:

Printed: SALES REPORT: sales-data-West

ReportProcessor sınıfının her zaman aynı üç adımı aynı sırayla çağırdığına, ancak her rapor türünün bu adımlar için kendi uygulamasını sağladığına dikkat et. Algoritmanın iskeleti sabit kalırken ayrıntılar değişir: işte Şablon Method kalıbı uygulamada böyle çalışır!

Kendin dene

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// Rapor türünü oku
	scanner.Scan()
	reportType := scanner.Text()
	
	// Yapılandırma değerini oku (bölge veya depo)
	scanner.Scan()
	configValue := scanner.Text()

	// TODO: reportType'a göre uygun generator'ı oluştur
	// - Eğer reportType "sales" ise, Region değeri configValue olan bir SalesReport oluştur
	// - Eğer reportType "inventory" ise, Warehouse değeri configValue olan bir InventoryReport oluştur
	
	// TODO: generator ile bir ReportProcessor oluştur
	
	// TODO: Generate() metodunu çağır ve sonucu yazdır
	_ = reportType
	_ = configValue
	fmt.Println("TODO: Generate and print the report")
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online Go derleyicisi