Adaptör Kalıbı
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 92 / 107.
Adapter deseni, mevcut bir türü yeni bir arayüzle sararak uyumsuz arayüzlerin birlikte çalışmasını sağlar. Command eylemleri kapsüllerken Adapter, bir arayüzü istemcilerin beklediği başka bir arayüze dönüştürür.
Uygulamanızın beklediğinden farklı bir yöntem imzası kullanan eski bir yazıcınız olduğunu düşünün:
// Uygulamanızın kullandığı hedef arayüz
type Printer interface {
Print(text string) string
}
// Uyumsuz arayüze sahip eski yazıcı
type OldPrinter struct{}
func (o OldPrinter) PrintDocument(doc string, copies int) string {
return fmt.Sprintf("Old printer: %s (x%d)", doc, copies)
}Adaptör, eski türü sarar ve beklenen arayüzü uygular:
type OldPrinterAdapter struct {
oldPrinter OldPrinter
}
func (a OldPrinterAdapter) Print(text string) string {
return a.oldPrinter.PrintDocument(text, 1)
}Artık eski yazıcı, Printer arayüzünü bekleyen kodla sorunsuz bir şekilde çalışıyor:
func PrintMessage(p Printer, msg string) string {
return p.Print(msg)
}
adapter := OldPrinterAdapter{oldPrinter: OldPrinter{}}
result := PrintMessage(adapter, "Hello") // "Old printer: Hello (x1)"Adapter kalıbı, üçüncü taraf kitaplıkları entegre ederken, eski kodla çalışırken veya arayüz gereksinimlerinizle eşleşmeyen mevcut sınıfları kullanmanız gerektiğinde paha biçilmezdir. Özgün kodu değiştirmeden bir köprü görevi görür.
Görev
KolayAdapter desenini kullanarak bir medya oynatıcı sistemi oluşturalım! Birleşik bir arayüz bekleyen modern bir ses oynatıcınız var, ancak tamamen farklı yöntem imzaları kullanan eski ses ekipmanlarını entegre etmeniz gerekiyor. Adaptörünüz bu boşluğu kapatarak eski donanımın yeni sistemle sorunsuz şekilde çalışmasını sağlayacak.
Kodunuzu üç dosyaya ayıracaksınız:
player.go: Hedef arayüzünüzü ve eski bir ses cihazını tanımlayın.Modern sisteminizin beklediği bir
AudioPlayerarayüzü oluşturun. Bu arayüzde, parça adını alan ve bir oynatma mesajı döndürenPlay(track string) stringyöntemi bulunmalıdır.Ayrıca bu arayüzle eşleşmeyen eski bir cihaz tanımlayın:
VinylPlayeryapısı, birSpeedRPMalanına (int) sahiptir.DropNeedle(record string, side string) stringdöndürenPlaying [record] ([side] side) at [speed]rpmyöntemine sahiptir.
VinylPlayer'ın arayüzü AudioPlayer ile uyumlu değildir. İki parametre gerektirir ve tamamen farklı bir yöntem adı kullanır.
adapter.go: Eski cihazı uyumlu hâle getiren adaptörünüzü oluşturun.Bir
VinylAdaptersaran veVinylPlayerarayüzünü uygulayanAudioPlayeryapısını oluşturun.Playçağrıldığında adaptör, yan parametresi için varsayılan olarakDropNeedledeğerini kullanarak vinyl oynatıcınınAyöntemini çağırmalıdır.Karşılaştırma için modern bir oynatıcı da oluşturun:
DigitalPlayeryapısı:PlayyöntemiStreaming: [track]döndürür
main.go: Her iki oynatıcının da aynı arayüz üzerinden çalıştığını gösterin.Müzik çalmak için arayüzü kullanan
PlayMusic(player AudioPlayer, track string) stringadlı bir işlev oluşturun. Bu işlevin dijital bir oynatıcı mı yoksa adaptörle uyarlanmış bir vinyl oynatıcı mı kullandığını bilmesine veya önemsemesine gerek olmamalıdır.Bir oynatıcı türü (
digitalveyavinyl) okuyun; vinyl ise RPM hızını da okuyun. Ardından parça adını okuyun. Uygun oynatıcıyı oluşturun (vinyl için adaptörü kullanarak), parçayıPlayMusicişleviniz aracılığıyla çalın ve sonucu yazdırın.
Aşağıdaki girdiler sağlanacaktır:
- 1. satır: Oynatıcı türü (
digitalveyavinyl) - 2. satır: RPM hızı (yalnızca vinyl ise)
- Son satır: Çalınacak parçanın adı
Örneğin, şu girdi verildiğinde:
digital
Bohemian RhapsodyÇıktınız şu olmalıdır:
Streaming: Bohemian RhapsodyVe şu girdi verildiğinde:
vinyl
33
Abbey RoadÇıktınız şu olmalıdır:
Playing Abbey Road (A side) at 33rpmVe şu girdi verildiğinde:
vinyl
45
Blue MondayÇıktınız şu olmalıdır:
Playing Blue Monday (A side) at 45rpmPlayMusic işlevinin her iki oynatıcıyla da aynı şekilde çalıştığına dikkat edin. Vinyl oynatıcının aslında tamamen farklı bir arayüzden uyarlandığı hakkında hiçbir bilgisi yoktur. Adaptör, modern arayüz çağrılarını perde arkasında eski biçime dönüştürür!
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
// PlayMusic, müzik çalmak için AudioPlayer arayüzünü kullanır
// Bu fonksiyon herhangi bir AudioPlayer uygulamasıyla çalışır
// TODO: Bu fonksiyonu player.Play(track) çağıracak ve sonucu döndürecek şekilde uygula
func PlayMusic(player AudioPlayer, track string) string {
// TODO: Bu fonksiyonu uygula
return ""
}
func main() {
reader := bufio.NewReader(os.Stdin)
// Oynatıcı türünü oku
playerType, _ := reader.ReadString('\n')
playerType = strings.TrimSpace(playerType)
var player AudioPlayer
var track string
if playerType == "vinyl" {
// Vinil için RPM hızını oku
rpmStr, _ := reader.ReadString('\n')
rpmStr = strings.TrimSpace(rpmStr)
rpm, _ := strconv.Atoi(rpmStr)
// Parça adını oku
track, _ = reader.ReadString('\n')
track = strings.TrimSpace(track)
// TODO: Verilen RPM ile bir VinylPlayer oluştur
// TODO: Onu bir VinylAdapter içine sar
// TODO: player değişkenine ata
_ = rpm // rpm kullandığınızda bu satırı kaldırın
} else {
// Parça adını oku
track, _ = reader.ReadString('\n')
track = strings.TrimSpace(track)
// TODO: Bir DigitalPlayer oluştur
// TODO: player değişkenine ata
}
// TODO: PlayMusic'i çağır ve sonucu yazdır
_ = player // player'ı kullandığında bu satırı kaldır
_ = track // track'i kullandığında bu satırı kaldır
}
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
1Go OOP Temelleri
Harici DosyalarGo Çalışma Alanı ve ModüllerPaketler ve İçe AktarmalarDışa Aktarılan ve Aktarılmayan İsimlerGo'da OOP'ye GirişSınıf Olarak Struct'larStruct'larda Metot TanımlamaPointer ve Değer AlıcılarStruct BaşlatmaYapıcı FonksiyonlarÖzet - Basit Hesap Makinesi4Arayüzler
Arayüzlere GirişÖrtük UygulamaSözleşme Olarak ArayüzBoş Arayüz (any)Tür OnaylamaTür SeçimiArayüz BileşimiStringer ve Error ArayüzleriÖzet - Şekil Hesaplayıcı7Kapsülleme
Dışa Aktarılan ve Aktarılmayan AlanlarPaket Seviyesinde KapsüllemeGetter ve Setter MetotlarıGo'da Bilgi GizlemeÖzet - Öğrenci Kayıtları10Generics (Go 1.18+)
Generics'e GirişTür ParametreleriTür KısıtlamalarıGeneric Struct'larGeneric Metotlar İçin Geçici ÇözümÖzet - Generic Koleksiyon13Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıAbstract Factory KalıbıObserver KalıbıStrategy Kalıbı2Türler ve Struct'lar: Derinlemesine İnceleme
Temel ve Bileşik TürlerÖzel Tür TanımlamalarıStruct EtiketleriAnonim Struct'larİç İçe Geçmiş Struct'larSıfır Değerler ve VarsayılanlarÖzet - Rehber5Kalıtım Yerine Kompozisyon
Go'da Neden Kalıtım YokStruct Gömme TemelleriMetot YükseltmeBirden Fazla Struct GömmeGömme vs AgregasyonGömülü Metotları GölgelemeÖzet - Çalışan Hiyerarşisi8Hata Yönetimi ve OOP
error ArayüzüÖzel Hata TürleriHata Sarmalama (fmt.Errorf)Sentinel Hatalarerrors.Is() ve errors.As()Panic, Defer ve RecoverÖzet - Dosya Ayrıştırıcı11Standart Kütüphane ve OOP
io.Reader ve io.Writersort.Interface Arayüzüfmt.Stringer ArayüzüStruct'lar ile encoding/jsonhttp.Handler ArayüzüÖzet - REST API Modelleri14Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit KalıbıDekoratör olarak Middleware3İşaretçiler ve Bellek
Go'da İşaretçi TemelleriStruct İşaretçileriDeğer ile Geçme ve Referans ile Geçmenew() FonksiyonuGo'da Garbage CollectionÖzet - Linked List Oluşturucu6Go'da Polimorfizm
Interface'ler ile PolimorfizmGo'da Duck TypingInterface Karşılama KurallarıPolimorfik KoleksiyonlarDependency InjectionÖzet - Payment Processor9Eşzamanlılık ve OOP
Goroutine TemelleriKanallar ve İletişimTamponlu ve Tamponsuz KanallarSelect İfadesisync.Mutex ve sync.RWMutexsync.WaitGroupThread-Safe Struct TasarımıÖzet - Worker PoolKendi başına pratik yap: Online Go derleyicisi