Yazılım geliştirmede kalıplar: gözlemci kalıbı

Adanali

Active member
Yazılım geliştirmede kalıplar: gözlemci kalıbı


  1. Yazılım geliştirmede kalıplar: gözlemci kalıbı

Kalıplar, modern yazılım geliştirmede önemli bir soyutlamadır. İyi tanımlanmış terminoloji, açık belgeler sunar ve en iyisinden öğrenirler. Gözlemci modeli, Design Patterns: Elements of Reusable Object-Oriented Software kitabından bir davranış modelidir. Nesneler arasında 1’den çoğa bağımlılıkları tanımlar, böylece bir nesnede yapılan değişiklikler tüm bağımlı nesnelerin bildirilmesine neden olur.







Rainer Grimm, uzun yıllardır yazılım mimarı, ekip lideri ve eğitim yöneticisi olarak çalışmaktadır. C++, Python ve Haskell programlama dilleri üzerine makaleler yazmaktan hoşlanır, aynı zamanda sık sık uzmanlık konferanslarında konuşmaktan da keyif alır. Modernes C++ blogunda yoğun bir şekilde C++ tutkusundan bahsediyor.













Observer modeli, klasik bir tasarım problemini çözer: önemli bir olay meydana geldiğinde tüm müşteri adaylarının otomatik olarak bilgilendirilmesini nasıl sağlarız?

gözlemci modeli


amaç

  • Nesneler arasında 1’den çoğa bağımlılıkları tanımlar, böylece bir nesnede yapılan değişiklikler tüm bağımlı nesnelerin bildirilmesine neden olur.
Ayrıca şöyle bilinir


  • Yayıncı-Abone (kısaca Pub/Sub)
kullanım durumu

  • Bir nesne başka bir nesnenin durumuna bağlıdır,
  • bir nesnedeki değişiklik başka bir nesnede değişikliğe neden olur,
  • Nesneler, sıkıca bağlı olmayan başka bir nesnenin durum değişikliklerinden haberdar edilmelidir.
çerçeve








Subject

  • Gözlemci koleksiyonunu yönetir
  • İzleyicilerin kendi kendine kayıt olmalarına ve abonelikten çıkmalarına izin verir
Observer

  • Gözlemcileri bilgilendirmek için bir arayüz tanımlar
ConcreteObserver

  • Arayüzü uygula
  • den olacak Subject bildirildi
misal


Aşağıdaki program observer.cpp önceki sınıf diyagramını uygular.


// observer.cpp

#include <iostream>
#include <list>
#include <string>

class Observer {
public:
virtual ~Observer(){};
virtual void notify() const = 0;
};

class Subject {
public:
void registerObserver(Observer* observer) {
observers.push_back(observer);
}
void unregisterObserver(Observer* observer) {
observers.remove(observer);
}
void notifyObservers() const { // (2)
for (auto observer: observers) observer->notify();
}

private:
std::list<Observer *> observers;
};

class ConcreteObserverA : public Observer {
public:
ConcreteObserverA(Subject& subject) : subject_(subject) {
subject_.registerObserver(this);
}
void notify() const override {
std::cout << "ConcreteObserverA::notifyn";
}
private:
Subject& subject_; // (3)
};

class ConcreteObserverB : public Observer {
public:
ConcreteObserverB(Subject& subject) : subject_(subject) {
subject_.registerObserver(this);
}
void notify() const override {
std::cout << "ConcreteObserverB::notifyn";
}
private:
Subject& subject_; // (4)
};


int main() {

std::cout << 'n';

Subject subject;
ConcreteObserverA observerA(subject);
ConcreteObserverB observerB(subject);

subject.notifyObservers();
std::cout << " subject.unregisterObserver(observerA)n";
subject.unregisterObserver(&observerA); // (1)
subject.notifyObservers();

std::cout << 'n';

}


the Observer üye işlevini destekler notify; konu üyelerin işlevlerini destekler registerObserver, unregisterObserver Ve notifyObservers. Somut gözlemciler, nesneyi yapıcılarına alır ve bildirim için kayıt olmak üzere kullanır. buna referansınız var mı Subject (3 ve 4). observerA (1)’de iptal edilir. üye işlevi notifyObservers kayıtlı tüm gözlemcileri inceler ve onlara bildirir (2).

Aşağıdaki ekran görüntüsü programın çıktısını göstermektedir:








Bir önceki programda observer.cpp Hafızayı bilerek istemedim. Sanallık genellikle, örneğin gömülü sistemlerde dinamik (yığın) bellek kullanılamadığında kullanılır. İşte uygun olanı main-Hafıza tahsisli işlev:


int main() {

std::cout << 'n';

Subject* subject = new Subject;
Observer* observerA = new ConcreteObserverA(*subject);
Observer* observerB = new ConcreteObserverB(*subject);

subject->notifyObservers();
std::cout <<
" subject->unregisterObserver(observerA)" << "n";
subject->unregisterObserver(observerA);
subject->notifyObservers();

delete observerA;
delete observerB;

delete subject;

std::cout << 'n';

}


bilinen kullanımlar

Gözlemci modeli, grafik kullanıcı arabirimleri için Model-View-Controller (MVC) veya olay işleme için reaktörler gibi mimari modellerde yaygın olarak kullanılır.

  • Model görünümü denetleyicisi: Model, verileri ve mantığını temsil eder. Model, görünümler gibi bağımlı bileşenlerini bilgilendirir. Bunlar, kullanıcı girişi için denetleyici olan verilerin görüntülenmesinden sorumludur.
  • reaktör: Reaktör olay tüccarlarını kaydeder. Eşzamanlı olay çoğullama çözücü (select) bir olay meydana geldiğinde operatörleri bilgilendirir.
Gelecekte her iki mimari modele de ayrı bir makale ayıracağım.

varyasyonlar

Programdaki konu observer.cpp örnekte bir bildirim gönderin. Daha gelişmiş iş akışları sıklıkla kullanılır:

konu gönderir

  • bir değer
  • bir değerin mevcut olduğuna dair bir bildirim; bundan sonra gözlemci onu almalıdır,
  • hangi değerin mevcut olduğunu içeren bir bildirim. Gözlemci gerekirse toplayacaktır.
İlgili modeller

Arabulucu modeli, bir gönderici ile alıcısı arasında iletişim kurar. İki uç nokta arasındaki tüm iletişim daha sonra bunlardan geçer. Aracı ve gözlemci birbirine çok benzer. Arabulucunun amacı, gönderici ve alıcıyı birbirinden ayırmaktır. Bunun yerine izleyici, yayıncı ve aboneleri arasında tek yönlü bir iletişim kurar.

Avantajlar ve dezavantajlar


faydalar

  • İzleyiciye (yayıncıya) kolayca yeni izleyiciler (aboneler) eklenebilir.
  • Gözlemciler çalışma zamanında abone olabilir ve abonelikten çıkabilir.
Dezavantajları

  • Yayıncı, bildirimlerin abonelere hangi sırayla gönderileceğini garanti etmez ve bildirimlerin ne kadar sürede teslim edileceğini belirtmez.
  • Yayıncı bir bildirim göndermiş olabilir, ancak bir abone artık aktif olmayabilir. Bu dezavantajdan kaçınmak için, somut gözlemcilerin yıkıcısı, kendi yıkıcılarında birbirini yok edecek şekilde uygulanabilir:

class ConcreteObserverA : public Observer {
public:
ConcreteObserverA(Subject& subject) : subject_(subject) {
subject_.registerObserver(this);
}
~ConcreteObserverA() noexcept {
subject_.unregisterObserver(this);
}
void notify() const override {
std::cout << "ConcreteObserverA::notifyn";
}
private:
Subject& subject_;
};


somut gözlemci ConcreteObserverA RAII deyimini uygular: yapıcısına kaydolun ve yıkıcısına kaydı silin.

Sıradaki ne?


Ziyaretçi modelinin kararsız bir itibarı vardır. Bir yandan, ziyaretçi çift gönderime izin verir. Öte yandan, Ziyaretçi’nin uygulanması oldukça karmaşıktır. Ziyaretçi modelini bir sonraki yazımda daha detaylı tanıtacağım.


()



Haberin Sonu
 
Üst