الگوی مشاهده گر روشی محبوب برای توزیع رویدادها در یک سیستم است. با زوایای آن آشنا شوید.
الگوی طراحی قالبی است که یک مشکل رایج در طراحی نرم افزار را حل می کند.
الگوی مشاهدهگر که به عنوان الگوی انتشار-اشتراک نیز شناخته میشود، یک الگوی رفتاری است. این به شما امکان می دهد چندین شی یا مشترک را در مورد هر رویدادی که در شیئی که مشاهده می کنند منتشر شده است مطلع کنید.
در اینجا نحوه پیاده سازی الگوی طراحی مشاهدهگر در TypeScript را یاد خواهید گرفت.
الگوی مشاهده گر
الگوی مشاهده گر با تعریف رابطه یک به چند بین ناشر و مشترکانش کار می کند. هنگامی که رویدادی در ناشر رخ می دهد، همه مشترکین آن رویداد را مطلع می کند. یکی از نمونه های گسترده این الگو، شنوندگان رویداد جاوا اسکریپت است.
برای زمینه، فرض کنید در حال ساخت یک ردیاب موجودی هستید که تعداد محصولات فروشگاه شما را ردیابی می کند. در این حالت فروشگاه شما موضوع/ناشر است و موجودی شما ناظر/مشترک است. استفاده از الگوی طراحی ناظر در این شرایط بهینه خواهد بود.
در الگوی طراحی مشاهدهگر، کلاس موضوعی شما باید سه روش را اجرا کند:
- یک روش پیوست این روش یک ناظر به موضوع اضافه می کند.
- یک روش جدا کردن این روش یک ناظر را از یک موضوع حذف می کند.
- یک روش اطلاع رسانی/به روز رسانی این روش هنگام تغییر حالت در سوژه به مشاهده کنندگان سوژه اطلاع می دهد.
کلاس ناظر شما باید یک متد را پیاده سازی کند، متد به روز رسانی. این روش زمانی واکنش نشان می دهد که تغییری در وضعیت سوژه آن ایجاد شود.
اجرای کلاس های سوژه و ناظر
اولین قدم برای پیاده سازی این الگو، ایجاد رابط هایی برای کلاس سوژه و ناظر است تا اطمینان حاصل شود که روش های صحیح را پیاده سازی می کنند:
// Subject/Publisher Interface
interface Subject {
attachObserver(observer: Observer): void;
detachObserver(observer: Observer): void;
notifyObserver(): void;
}
// Observer/Subscriber Interface
interface Observer {
update(subject: Subject): void;
}
رابطهای موجود در بلوک کد بالا روشهایی را که کلاسهای بتن شما باید پیادهسازی کنند، تعریف میکنند.
کلاس موضوعی مشخص
گام بعدی پیاده سازی یک کلاس موضوع مشخص است که رابط Subject را پیاده سازی می کند:
// Subject
class Store implements Subject {}
سپس وضعیت Subject را در کلاس Store مقداردهی اولیه کنید. ناظران سوژه به تغییرات این حالت واکنش نشان خواهند داد.
در این حالت، حالت یک عدد است و ناظران به افزایش تعداد واکنش نشان خواهند داد:
// Subject state
private numberOfProducts: number;
سپس، آرایه ای از ناظران را مقداردهی اولیه کنید. این آرایه به این صورت است که شما ناظران را ردیابی خواهید کرد:
// initializing observers
private observers: Observer[] = [];
ممکن است برخی از پیادهسازیهای الگوی مشاهدهگر را با استفاده از ساختار داده Set به جای یک آرایه برای پیگیری ناظر بیابید. استفاده از یک مجموعه تضمین می کند که مشاهده گر یکسان دو بار ظاهر نمی شود. اگر میخواهید به جای آن از یک آرایه استفاده کنید، باید مشاهدهگرهای تکراری را در روش پیوست خود بررسی کنید.
در مرحله بعد، شما باید متدهای موضوع – پیوست، جدا کردن، و اطلاع رسانی/به روز رسانی- را در کلاس بتن خود پیاده کنید.
برای پیاده سازی متد پیوست، ابتدا بررسی کنید که آیا مشاهده گر قبلاً متصل شده است یا خیر و در صورت وجود خطا پرتاب کنید. در غیر این صورت، مشاهده گر را با استفاده از روش آرایه جاوا اسکریپت به آرایه اضافه کنید، فشار دهید:
// 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(&aposObserver has already been subscribed &apos);
}
// Add a new observer
this.observers.push(observer);
}
در مرحله بعد، متد جداسازی خود را با پیدا کردن ایندکس و حذف آن از آرایه با استفاده از متد جاوا اسکریپت اجرا کنید.
ممکن است سناریوهایی وجود داشته باشد که در آن ناظری که میخواهید جدا کنید قبلاً جدا شده است یا از ابتدا مشترک نشده است. شما باید این سناریوها را با اضافه کردن یک دستور شرطی کنترل کنید تا بررسی کنید که آیا مشاهدهگر در آرایه یا مجموعه قرار دارد یا خیر.
// 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(&aposObserver does not exist&apos);
}
this.observers.splice(observerIndex, 1);
console.log(&aposObserver detached...&apos);
}
در مرحله بعد، روش اطلاع رسانی/به روز رسانی خود را با چرخش بر روی فهرست ناظران خود و فراخوانی روش به روز رسانی هر یک اجرا کنید:
// Notifying Observers
notifyObserver(): void {
console.log(&aposNotifying observers...&apos);
for (const observer of this.observers) {
observer.update(this);
}
}
در نهایت، برای کلاس Subject، متدی را پیاده سازی کنید که حالت را دستکاری می کند و سپس با فراخوانی متد notify/update ناظران را از تغییر مطلع می کند. این مثال سادهسازی این است که چگونه یک سوژه ممکن است یک عمل را انجام دهد و سپس به ناظران اطلاع دهد:
// Changing state and notifying observers
newProduct(products: number): void {
this.numberOfProducts += products;
console.log(&aposNew product added to the store&apos);
this.notifyObserver();
}
کلاس های مشاهده گر بتن
برای اشتراک در ناشر یک کلاس یا کلاس های ناظر ایجاد کنید. هر کلاس ناظر باید رابط Observer را پیاده سازی کند.
کلاسهای مشاهدهگر یک روش اطلاعرسانی/بهروزرسانی را اجرا میکنند که فقط موضوعی که مشاهده میکنند باید آن را فراخوانی کند. این روش باید شامل تمام منطق تجاری باشد که باید در پاسخ به تغییر وضعیت موضوع اجرا کنید:
// Concrete Observer 1
class Inventory implements Observer {
update(): void {
console.log(&aposNew product added to the store, updating inventory...&apos);
// Actual business logic goes here...
}
}
// Concrete Observer 2
class Customer implements Observer {
update(): void {
console.log(&aposNew product added to the store, I have to go check it out...&apos);
// Actual business logic goes here...
}
}
با استفاده از الگوی مشاهده گر
برای استفاده از این الگو، کلاسهای موضوع عینی و ناظر را نمونهسازی کنید. پس از انجام این کار، متد Subject’s attach را فراخوانی کنید و نمونه Observer را به عنوان آرگومان ارسال کنید. در پاسخ، موضوع آن نمونه را به فهرست ناظران خود اضافه خواهد کرد:
// 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);
این کد یک تغییر حالت را شبیه سازی می کند. این تغییر متد notify را در کلاس Subject فعال می کند. این روش به نوبه خود متد notify را بر روی هر یک از ناظران خود فراخوانی می کند. سپس هر ناظر منطق تجاری خود را اجرا خواهد کرد.
شما فقط زمانی باید از این الگو استفاده کنید که تغییرات در وضعیت یک شیء بر اشیاء دیگر تأثیر بگذارد و مجموعه اشیاء درگیر ناشناخته یا پویا باشد.
مزایای استفاده از الگوی مشاهدهگر
استفاده از این الگو در کد به شما اجازه می دهد تا اصل باز/بستن را حفظ کنید. میتوانید هر تعداد مشترک که میخواهید اضافه کنید و در زمان اجرا، بدون تغییر کد موضوع، روابط بین اشیا را برقرار کنید.