برنامه نویسی

الگوی Singleton در برنامه React

💭 مقدمه

در این مقاله، می‌خواهم تجربه‌ام را در استفاده از الگوی تک‌تن به‌عنوان یک سرویس در داخل اپلیکیشن تولیدی React به اشتراک بگذارم.

🌧️ مشکل

ما جاهای زیادی برای رسیدگی به منطق بومی سازی داشتیم. برنامه ما یک برنامه وب چند زبانه است که از سه زبان پشتیبانی می کند. این منجر به تعامل مداوم با محلی سازی می شود. با این حال، مسئله این است که توابع در سراسر برنامه برای همه ابزارهای متصل به محلی سازی پخش می شوند. گاهی اوقات، حتی یک تابع از مجموعه ای از دو زبان و سه زبان دیگر استفاده می کرد. چنین آشفتگی باعث ایجاد اشکالات و سوء تفاهم می شد.

⚡️ راه حل الگو

چنین کاری را می توان با اجرای یک الگوی تکی حل کرد زیرا در کل برنامه به اشتراک گذاشته شده است و کنترل دسترسی دقیقی را فراهم می کند. این به تیم ما کمک کرد تا کمک‌کنندگان محلی‌سازی را در یک مکان متمرکز کند، و همچنین به ما کمک می‌کند تا با ارائه مستندات واضح برای روش‌ها و استفاده از سرویس، خطر اشکالات و سوء تفاهم را کاهش دهیم.

🤔 الگوی سینگلتون چیست؟

“Singleton یک الگوی طراحی خلاقانه است که به شما امکان می دهد اطمینان حاصل کنید که یک کلاس فقط یک نمونه دارد در حالی که یک نقطه دسترسی جهانی به این نمونه ارائه می دهد.” – گورو بازسازی.

💡 طبق بیانیه دقیقاً همان چیزی است که ما نیاز داریم!

اول، ما باید فقط یک نمونه در کل برنامه داشته باشیم، که باید منبع حقیقت باشد.

دوم، نمونه باید به صورت سراسری قابل دسترسی باشد و از رونویسی از قسمت دیگری از برنامه محافظت شود، زیرا کل برنامه باید از همان تعداد زبان استفاده کند.

💻 پیاده سازی

1) تعریف کلاس Singleton

export class LocalisationService {
    private static instance: LocalisationService
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این ساختار اصلی کلاس Singleton ما، LocalisationService است. ما یک نمونه متغیر استاتیک خصوصی از همان کلاس را اعلام می کنیم. این متغیر نمونه واحد کلاس ما را نگه می دارد.

2) سازنده خصوصی و روش ایجاد استاتیک

private constructor() {
    this.languages = {
      [LanguageCode.EN]: {
        shortName: LanguageCode.EN,
        longName: LanguageName.ENGLISH,
      },
      [LanguageCode.DE]: {
        shortName: LanguageCode.DE,
        longName: LanguageName.DEUTSCH,
      },
      [LanguageCode.FR]: {
        shortName: LanguageCode.FR,
        longName: LanguageName.FRANCAIS,
      },
    }
}

public static getInstance(): LocalizationService {
  if (!LocalizationService.instance) {
    LocalizationService.instance = new LocalizationService()
  }

  return LocalizationService.instance
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در اینجا، ما یک سازنده خصوصی داریم که شی زبان ها را مقداردهی اولیه می کند. سازنده خصوصی است تا از ایجاد نمونه های جدید کلاس از خارج جلوگیری کند. متد getInstance یک متد استاتیک عمومی است که نمونه واحد کلاس LocalizationService را برمی گرداند. اگر نمونه وجود نداشته باشد، نمونه جدیدی ایجاد می کند.

3) روش های عمومی

export enum LanguageCode {
  EN = "en",
  DE = "de",
  FR = "fr",
}

export enum LanguageName {
  ENGLISH = "English",
  DEUTSCH = "Deutsch",
  FRANCAIS = "Français",
}
export interface Language {
  shortName: LanguageCode
  longName: LanguageName
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اینها متدهای عمومی کلاس Singleton ما هستند. getAllLanguages ​​همه زبان های موجود را برمی گرداند. getLanguageByShortName یک زبان خاص را با نام کوتاهش برمی گرداند. getLanguagesExcept همه زبان ها را به جز زبانی که توسط کلید مشخص شده است برمی گرداند.

4) استفاده از سرویس Singleton

import { LanguageCode, LocalizationService } from "services"

const localizationService = LocalizationService.getInstance()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این روشی است که ما از سرویس Singleton خود در کد خود استفاده می کنیم. ما LocalizationService را وارد کرده و متد getInstance را فراخوانی می کنیم تا نمونه واحدی از سرویس را دریافت کنیم.

کد کل سرویس

export enum LanguageCode {
  EN = "en",
  DE = "de",
  FR = "fr",
}

export enum LanguageName {
  ENGLISH = "English",
  DEUTSCH = "Deutsch",
  FRANCAIS = "Français",
}
export interface Language {
  shortName: LanguageCode
  longName: LanguageName
}

/**
 * Represents the localization service, responsible for managing language-related tasks.
 * This class follows the Singleton pattern to ensure only one instance is used throughout the application.
 */
export class LocalizationService {
  private static instance: LocalizationService
  private readonly languages: { [key: string]: Language }

  /**
   * Initializes a new instance of the LocalizationService class.
   * The constructor is private to prevent instantiation from outside the class.
   */
  private constructor() {
    this.languages = {
      [LanguageCode.EN]: {
        shortName: LanguageCode.EN,
        longName: LanguageName.ENGLISH,
      },
      [LanguageCode.DE]: {
        shortName: LanguageCode.DE,
        longName: LanguageName.DEUTSCH,
      },
      [LanguageCode.FR]: {
        shortName: LanguageCode.FR,
        longName: LanguageName.FRANCAIS,
      },
    }
  }

  /**
   * Retrieves the single instance of the LocalizationService class.
   * If an instance does not exist, it creates a new one.
   * @returns {LocalizationService} The single instance of the LocalizationService class.
   */
  public static getInstance(): LocalizationService {
    if (!LocalizationService.instance) {
      LocalizationService.instance = new LocalizationService()
    }

    return LocalizationService.instance
  }

  /**
   * Retrieves an array of all available languages.
   * @returns {Language[]} An array containing all available languages.
   */
  public getAllLanguages(): Language[] {
    return Object.values(this.languages)
  }

  /**
   * Retrieves a language by its short name.
   * @param {LanguageCode} shortName - The short name of the language to retrieve.
   * @returns {Language | undefined} The language with the specified short name, or undefined if not found.
   */
  public getLanguageByShortName(shortName: LanguageCode): Language | undefined {
    return this.languages[shortName]
  }

  /**
   * Retrieves an array of all languages except the one specified by the key.
   * @param {LanguageCode} key - The key of the language to exclude from the result.
   * @returns {Language[]} An array containing all languages except the one specified by the key.
   */
  public getLanguagesExcept(key: LanguageCode): Language[] {
    return this.getAllLanguages().filter((language) => language.shortName !== key)
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

🏁 نتیجه

من احساس خوبی در مورد اینکه چگونه این الگو در اکوسیستم توسعه برنامه React قرار می گیرد، دارم. ما قبلاً شاهد موفقیت آن از طریق کتابخانه های محبوبی مانند Redux بودیم. پیاده‌سازی این الگو در یک برنامه تولید، مزایای توسعه را از نظر ثبات و سرعت توسعه برای ما به ارمغان آورد.

اگر در مورد این یا سایر الگوها سؤالی دارید، بیایید آنها را در نظرات مطرح کنیم!

🧐 آیا نمونه دیگری از اجرای الگوی طراحی در پایگاه کد React خود دارید؟ به اشتراک بگذارید!

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا