Tasarım deseni, yazılım tasarımında yaygın olarak tekrarlanan bir sorunu çözen bir şablondur.
Yayınla-abone ol modeli olarak da bilinen gözlemci kalıbı, bir davranış kalıbıdır. Birden çok nesneyi veya aboneyi, gözlemledikleri nesnede yayınlanan herhangi bir olay hakkında bilgilendirmenize olanak tanır.
Burada TypeScript’te gözlemci tasarım deseninin nasıl uygulanacağını öğreneceksiniz.
Gözlemci Modeli
Gözlemci modeli, yayıncı ve aboneleri arasında bire çok ilişki tanımlayarak çalışır. Yayıncıda bir olay meydana geldiğinde, tüm aboneleri o olayla ilgili bilgilendirecektir. Bu kalıbın yaygın bir örneği JavaScript olay dinleyicileridir .
Bağlam için, mağazanızdaki ürün sayısını takip eden bir envanter izleyici oluşturduğunuzu varsayalım. Bu durumda mağazanız konu/yayıncı, envanteriniz ise gözlemci/abonedir. Bu durumda gözlemci tasarım modelini kullanmak en uygunudur.
Gözlemci tasarım modelinde, konu sınıfınız üç yöntem uygulamalıdır:
- Bir ekleme yöntemi. Bu yöntem konuya bir gözlemci ekler.
- Bir ayırma yöntemi. Bu yöntem, bir gözlemciyi bir konudan uzaklaştırır.
- Bir bildirim/güncelleme yöntemi. Bu yöntem, öznedeki durum değiştiğinde öznenin gözlemcilerini bilgilendirir.
- Gözlemci sınıfınız, güncelleme yöntemi olan bir yöntemi uygulamalıdır. Bu yöntem, öznesinin durumunda bir değişiklik olduğunda tepki verir.
Konu ve Gözlemci Sınıflarının Uygulanması
Bu kalıbı uygulamanın ilk adımı, doğru yöntemleri uyguladıklarından emin olmak için konu ve gözlemci sınıfı için arayüzler oluşturmaktır:
// Subject/Publisher Interface
interface Subject {
attachObserver(observer: Observer): void;
detachObserver(observer: Observer): void;
notifyObserver(): void;
}
// Observer/Subscriber Interface
interface Observer {
update(subject: Subject): void;
}
Yukarıdaki kod bloğundaki arabirimler, somut sınıflarınızın uygulaması gereken yöntemleri tanımlar.
Somut Bir Konu Sınıfı
Sonraki adım, Konu arabirimini uygulayan somut bir konu sınıfını uygulamaktır :
// Subject
class Store implements Subject {}
Ardından, Store sınıfında Konunun durumunu başlatın. Konunun gözlemcileri bu durumdaki değişikliklere tepki göstereceklerdir.
Bu durumda, durum bir sayıdır ve gözlemciler sayıdaki artışa tepki verirler:
// Subject state
private numberOfProducts: number;
Ardından, bir dizi gözlemciyi başlatın. Bu dizi, gözlemcileri nasıl izleyeceğinizdir:
// initializing observers
private observers: Observer[] = [];
Gözlemciyi takip etmek için bir dizi yerine bir Set veri yapısı kullanarak gözlemci modelinin bazı uygulamalarını bulabilirsiniz . Bir Set kullanmak, aynı gözlemcinin iki kez görünmemesini sağlayacaktır. Bunun yerine bir dizi kullanmak istiyorsanız, ekleme yönteminizde yinelenen gözlemciler olup olmadığını kontrol etmelisiniz.
Daha sonra, Somut sınıfınızda Konunun yöntemlerini – ekle , ayır ve bildir/güncelle – uygulamalısınız.
Ekleme yöntemini uygulamak için önce gözlemcinin zaten bağlı olup olmadığını kontrol edin ve varsa bir hata atın. Aksi takdirde, gözlemciyi JavaScript dizi yöntemini kullanarak diziye ekleyin , push :
// Attaching Observer(s)
attachObserver(observer: Observer): void {
// Check if the observer has already been attached
const observerExists = this.observers.includes(observer);
if (observerExists) {
throw new Error(‘Observer has already been subscribed ‘);
}
// Add a new observer
this.observers.push(observer);
}
Ardından, dizini bulup JavaScript ekleme yöntemini kullanarak diziden kaldırarak ayırma yönteminizi uygulayın .
Ayırmaya çalıştığınız gözlemcinin zaten ayrılmış olduğu veya ilk etapta abone olmadığı senaryolar olabilir. Bu senaryoları, duruma göre gözlemcinin dizide mi yoksa kümede mi olduğunu kontrol etmek için bir koşullu ifade ekleyerek ele almalısınız.
// Detaching Observer(s)
detachObserver(observer: Observer): void {
console.log(`Detaching observer ${JSON.stringify(observer)}`);
const observerIndex = this.observers.indexOf(observer);
if (observerIndex === -1) {
throw new Error(‘Observer does not exist’);
}
this.observers.splice(observerIndex, 1);
console.log(‘Observer detached…’);
}
Ardından, gözlemciler listenizin üzerinden geçerek ve her birinin güncelleme yöntemini çağırarak bildir/güncelleme yönteminizi uygulayın:
// Notifying Observers
notifyObserver(): void {
console.log(‘Notifying observers…’);
for (const observer of this.observers) {
observer.update(this);
}
}
Son olarak, Subject sınıfı için durumu işleyen ve ardından notify/update yöntemini çağırarak gözlemcilere değişikliği bildiren bir yöntem uygulayın. Bu örnek, bir öznenin bir eylemi nasıl gerçekleştirebileceğini ve ardından gözlemcileri nasıl bilgilendirebileceğinin basitleştirilmesidir:
// Changing state and notifying observers
newProduct(products: number): void {
this.numberOfProducts += products;
console.log(‘New product added to the store’);
this.notifyObserver();
}
Beton Gözlemci Sınıfları
Yayıncıya abone olmak için bir gözlemci sınıfı veya sınıfları oluşturun. Her gözlemci sınıfı, Gözlemci arabirimini uygulamalıdır.
Gözlemci sınıflar, yalnızca gözlemledikleri konunun çağırması gereken bir bildirim/güncelleme yöntemini uygulayacaktır. Bu yöntem, öznenin durumundaki bir değişikliğe yanıt olarak çalıştırmanız gereken tüm iş mantığını içermelidir:
// Concrete Observer 1
class Inventory implements Observer {
update(): void {
console.log(‘New product added to the store, updating inventory…’);
// Actual business logic goes here…
}
}
// Concrete Observer 2
class Customer implements Observer {
update(): void {
console.log(‘New product added to the store, I have to go check it out…’);
// Actual business logic goes here…
}
}
Gözlemci Modelini Kullanma
Bu kalıbı kullanmak için somut özne ve gözlemci sınıflarını somutlaştırın. Bunu yaptıktan sonra, Konunun ekleme yöntemini çağırın ve Observer örneğini argüman olarak iletin. Yanıt olarak, konu bu örneği gözlemciler listesine ekleyecektir:
// Instantiating Subject and Observer
const store = new Store();
const inventory = new Inventory();
const customer = new Customer()
// Subscribing objects to publisher
store.attachObserver(inventory);
store.attachObserver(customer);
// Changing subject state
store.newProduct(30);
Bu kod, bir durum değişikliğini simüle eder. Değişiklik, Subject sınıfındaki notify yöntemini tetikleyecektir . Bu yöntem, sırayla, gözlemcilerinin her birinde notify yöntemini çağırır. Her gözlemci daha sonra kendi iş mantığını çalıştıracaktır.
Bu kalıbı yalnızca bir nesnenin durumundaki değişiklikler diğer nesneleri etkilediğinde ve ilgili nesneler kümesi bilinmediğinde veya dinamik olduğunda kullanmalısınız.
Gözlemci Modelini Kullanmanın Avantajları
Bu kalıbı kodunuzda kullanmak, aç/kapat ilkesini korumanıza izin verir. İstediğiniz kadar abone ekleyebilir ve çalışma zamanında, konunun kodunu değiştirmeden nesneler arasında ilişkiler kurabilirsiniz.