الگوی طراحی Singleton: مدیریت کشورهای جهانی در برنامه های کاربردی شما

Summarize this content to 400 words in Persian Lang
آیا تا به حال متوجه شده اید که با یک شی سروکار دارید که باید در چندین بخش برنامه شما به اشتراک گذاشته شود – شاید یک اتصال پایگاه داده، یک سرویس گیرنده WebSocket یا یک مدیر پیکربندی؟
چگونه چنین شی ای را مدیریت می کنید تا در طول چرخه عمر برنامه یا فرآیند سازگار و قابل دسترسی باقی بماند؟ اینجاست که الگوی طراحی Singleton وارد بازی می شود.
نمای کلی
سینگلتون یک است الگوی طراحی خلاقانه ، که دسته ای از الگوهای طراحی است که به مشکلات مختلفی می پردازد که با روش بومی ایجاد اشیا با جدید کلمه کلیدی یا عملگر
را الگوی طراحی Singleton بر حل دو مشکل اصلی تمرکز دارد:
چگونه می توانیم a نقطه دسترسی جهانی به مثال ما؟
چگونه می توانیم اطمینان حاصل کنیم که الف کلاس یا نوع خاصی از اشیاء فقط یک نمونه دارد؟
این می تواند نحوه مدیریت نوع یا نوع خاصی از حالت جهانی مانند اتصالات پایگاه داده، سرویس گیرندگان WebSocket، سرویس های کش یا هر چیزی را که نیاز داریم در طول چرخه عمر برنامه در حافظه باقی بماند و تغییر کند، ساده و استاندارد کند.
چگونه می توانیم الگوی طراحی Singleton را پیاده سازی کنیم؟
طرحواره بالا به این کلاس TypeScript ترجمه می شود:
نمونه TypeScript
class Singleton {
private static instance: Singleton
// other properties…
public authorName: string
private constructor({ authorName }: { authorName: string }) {
this.authorName = authorName
}
public static getInstance(params) {
if (!this.instance) {
this.instance = new Singleton(params)
}
return this.instance
}
// other methods…
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
کلاس باید یک ویژگی ثابت برای ذخیره نمونه قابل اشتراک گذاری منحصر به فرد تعریف کند.
کلمه کلیدی static به این معنی است که شی نمونه با نمونه های کلاس مرتبط نیست بلکه با خود تعریف کلاس مرتبط است.
سازنده کلاس باید به عنوان خصوصی علامت گذاری شود. تنها راه برای به دست آوردن نمونه ای از کلاس ما، تماس با آن است getInstance روش استاتیک
const instance = Singleton.getInstance({ authorName: “Sidali Assoul” })
// let’s imagine
const instance1 = Singleton.getInstance({ authorName: “Sidali Assoul” }) // “Sidali Assoul”
const instance2 = Singleton.getInstance({ authorName: “John Doe” }) // “Sidali Assoul”
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
با فراخوانی متد static می توانیم از کلاس فوق استفاده کنیم getInstance که با کلاس Singleton مرتبط است.
را getInstance متد به ما تضمین میکند که همیشه همان نمونه را دریافت میکنیم، حتی اگر کلاس خود را چندین بار در مکانهای مختلف پایگاه کد خود نمونهسازی کنیم.
بنابراین هر دو متغیر (instance1 و instance2) همان نمونه تکی را به اشتراک بگذارید.
اولین سناریوی عملی
پریسما یک ORM شناخته شده در اکوسیستم جاوا اسکریپت است. برای استفاده از Prisma در برنامه خود، باید a را وارد کنید PrismaClient سپس یک شی را از آن نمونه سازی کنید.
import { PrismaClient } from “@prisma/client”
export const prismaClient = new PrismaClient()
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
را مشتری پریسما به شیوه ای تنبل یا به عبارت دیگر، تنها زمانی به پایگاه داده متصل می شود که برای اولین بار سعی می کنید یک موجودیت را پرس و جو کنید یا جهش دهید.
import { prismaClient } from “@/db”
const users = await prismaClient.user.findMany() // query on the users table
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
هر بار که prismaClient در یک فایل وارد می شود، یک نمونه جدید از آن ساخته می شود PrismaClient. از این رو، هر بار که از آن نمونه ها استفاده می کنیم، بسیاری از اتصالات پایگاه داده برقرار می شوند.
export const prismaClient = new PrismaClient() // a new instance is created every time it gets imported then used.
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
بسیاری از اتصالات پایگاه داده باز عملکرد برنامه شما را کاهش می دهند و حتی ممکن است منجر به خاموش شدن پایگاه داده شوند زیرا پایگاه داده ها معمولاً فقط می توانند تعداد محدودی از اتصالات را مدیریت کنند.
را الگوی طراحی Singleton می تواند به ما کمک کند با اجتناب از داشتن بیش از یک نمونه از چنین موضوعی جلوگیری کنیم PrismaClient کلاس و با ارائه یک نقطه واحد برای دسترسی به آن از طریق PrismaClientSingleton.getInstance() روش استاتیک
import { PrismaClient } from “@prisma/client”
class PrismaClientSingleton {
private static instance: PrismaClient
private constructor() {}
public static getInstance(): PrismaClient {
if (!PrismaClientSingleton.instance) {
PrismaClientSingleton.instance = new PrismaClient()
}
return PrismaClientSingleton.instance
}
}
export default PrismaClientSingleton
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
سناریوی عملی دوم
سناریوی عملی دیگری که ما از آن عبور خواهیم کرد، یک سناریوی است سرویس محدود کننده نرخ درون حافظه.
کاربران یا هکرها میتوانند یک نقطه پایانی خاص را با درخواستهای فراوان به آن اسپم کنند. این می تواند منجر به آسیب پذیری ها، هزینه های غیرمنتظره یا خرابی سرور شود.
برای جلوگیری از آن، میتوانیم یک سرویس محدودکننده نرخ درون حافظه را پیادهسازی کنیم.
این سرویس باید تعداد درخواستها را محدود کند IP آدرس برای یک بازه زمانی خاص (مثلاً 60 ثانیه).
class RateLimiterService {
private static instance: RateLimiterService
private requests: Map
private readonly limit: number // Maximum number of requests
private readonly window: number // Time window in milliseconds
private constructor(limit: number = 5, window: number = 60000) {
this.requests = new Map()
this.limit = limit
this.window = window
}
// Method to get a unique singleton instance
public static getInstance(): RateLimiterService {
if (!RateLimiterService.instance) {
RateLimiterService.instance = new RateLimiterService()
}
return RateLimiterService.instance
}
public isRateLimited(ip: string): boolean {
const currentTime = Date.now()
const userRequestData = this.requests.get(ip)
if (userRequestData) {
const isExpired =
currentTime – userRequestData.lastRequestTime > this.window
if (isExpired) {
userRequestData.count = 1
userRequestData.lastRequestTime = currentTime
return false
} else {
userRequestData.count++
if (userRequestData.count > this.limit) {
return true
}
return false
}
} else {
this.requests.set(ip, { count: 1, lastRequestTime: currentTime })
return false
}
}
}
export default RateLimiterService
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
را RateLimiterService کلاس نقشه ای را ذخیره می کند که تعداد درخواست ها را ردیابی می کند (requests[ip].count) ساخته شدن توسط یک کاربر خاص که توسط یک شناسایی شده است آدرس IP (کلید نقشه) در یک پنجره زمان بندی داده شده (requests[ip].lastRequestTime).
ما RateLimiterService قرار است به صورت جهانی مورد استفاده قرار گیرد، یا به عبارت دیگر، ما نمی خواهیم مقادیر حالت داخلی متشکل از requests نقشه، limit، و window متغیرها هر بار RateLimiterService وارد می شود
نتیجه گیری
را الگوی طراحی Singleton یک ابزار قدرتمند برای مدیریت موثر منابع مشترک در برنامه های ما است
خوراکی های کلیدی:
Singleton تضمین می کند که یک کلاس فقط یک نمونه دارد و یک نقطه دسترسی جهانی به آن فراهم می کند.
برای مدیریت منابع مشترک مانند اتصالات پایگاه داده، تنظیمات پیکربندی یا حافظه پنهان مفید است.
کاربردهای عملی شامل بهینه سازی ارتباطات پایگاه داده با ORMهایی مانند Prisma و پیاده سازی خدمات محدود کننده نرخ است.
تماس بگیرید
اگر سوالی دارید یا می خواهید در مورد چیزی بیشتر بحث کنید، با من در اینجا تماس بگیرید.
کد نویسی مبارک!
آیا تا به حال متوجه شده اید که با یک شی سروکار دارید که باید در چندین بخش برنامه شما به اشتراک گذاشته شود – شاید یک اتصال پایگاه داده، یک سرویس گیرنده WebSocket یا یک مدیر پیکربندی؟
چگونه چنین شی ای را مدیریت می کنید تا در طول چرخه عمر برنامه یا فرآیند سازگار و قابل دسترسی باقی بماند؟ اینجاست که الگوی طراحی Singleton وارد بازی می شود.
نمای کلی
سینگلتون یک است الگوی طراحی خلاقانه ، که دسته ای از الگوهای طراحی است که به مشکلات مختلفی می پردازد که با روش بومی ایجاد اشیا با جدید کلمه کلیدی یا عملگر
را الگوی طراحی Singleton بر حل دو مشکل اصلی تمرکز دارد:
- چگونه می توانیم a نقطه دسترسی جهانی به مثال ما؟
- چگونه می توانیم اطمینان حاصل کنیم که الف کلاس یا نوع خاصی از اشیاء فقط یک نمونه دارد؟
این می تواند نحوه مدیریت نوع یا نوع خاصی از حالت جهانی مانند اتصالات پایگاه داده، سرویس گیرندگان WebSocket، سرویس های کش یا هر چیزی را که نیاز داریم در طول چرخه عمر برنامه در حافظه باقی بماند و تغییر کند، ساده و استاندارد کند.
چگونه می توانیم الگوی طراحی Singleton را پیاده سازی کنیم؟
طرحواره بالا به این کلاس TypeScript ترجمه می شود:
نمونه TypeScript
class Singleton {
private static instance: Singleton
// other properties...
public authorName: string
private constructor({ authorName }: { authorName: string }) {
this.authorName = authorName
}
public static getInstance(params) {
if (!this.instance) {
this.instance = new Singleton(params)
}
return this.instance
}
// other methods...
}
- کلاس باید یک ویژگی ثابت برای ذخیره نمونه قابل اشتراک گذاری منحصر به فرد تعریف کند.
کلمه کلیدی static
به این معنی است که شی نمونه با نمونه های کلاس مرتبط نیست بلکه با خود تعریف کلاس مرتبط است.
- سازنده کلاس باید به عنوان خصوصی علامت گذاری شود. تنها راه برای به دست آوردن نمونه ای از کلاس ما، تماس با آن است
getInstance
روش استاتیک
const instance = Singleton.getInstance({ authorName: "Sidali Assoul" })
// let's imagine
const instance1 = Singleton.getInstance({ authorName: "Sidali Assoul" }) // "Sidali Assoul"
const instance2 = Singleton.getInstance({ authorName: "John Doe" }) // "Sidali Assoul"
با فراخوانی متد static می توانیم از کلاس فوق استفاده کنیم getInstance
که با کلاس Singleton مرتبط است.
را getInstance
متد به ما تضمین میکند که همیشه همان نمونه را دریافت میکنیم، حتی اگر کلاس خود را چندین بار در مکانهای مختلف پایگاه کد خود نمونهسازی کنیم.
بنابراین هر دو متغیر (instance1
و instance2
) همان نمونه تکی را به اشتراک بگذارید.
اولین سناریوی عملی
پریسما یک ORM شناخته شده در اکوسیستم جاوا اسکریپت است. برای استفاده از Prisma در برنامه خود، باید a را وارد کنید PrismaClient
سپس یک شی را از آن نمونه سازی کنید.
import { PrismaClient } from "@prisma/client"
export const prismaClient = new PrismaClient()
را مشتری پریسما به شیوه ای تنبل یا به عبارت دیگر، تنها زمانی به پایگاه داده متصل می شود که برای اولین بار سعی می کنید یک موجودیت را پرس و جو کنید یا جهش دهید.
import { prismaClient } from "@/db"
const users = await prismaClient.user.findMany() // query on the users table
هر بار که prismaClient
در یک فایل وارد می شود، یک نمونه جدید از آن ساخته می شود PrismaClient
. از این رو، هر بار که از آن نمونه ها استفاده می کنیم، بسیاری از اتصالات پایگاه داده برقرار می شوند.
export const prismaClient = new PrismaClient() // a new instance is created every time it gets imported then used.
بسیاری از اتصالات پایگاه داده باز عملکرد برنامه شما را کاهش می دهند و حتی ممکن است منجر به خاموش شدن پایگاه داده شوند زیرا پایگاه داده ها معمولاً فقط می توانند تعداد محدودی از اتصالات را مدیریت کنند.
را الگوی طراحی Singleton می تواند به ما کمک کند با اجتناب از داشتن بیش از یک نمونه از چنین موضوعی جلوگیری کنیم PrismaClient
کلاس و با ارائه یک نقطه واحد برای دسترسی به آن از طریق PrismaClientSingleton.getInstance()
روش استاتیک
import { PrismaClient } from "@prisma/client"
class PrismaClientSingleton {
private static instance: PrismaClient
private constructor() {}
public static getInstance(): PrismaClient {
if (!PrismaClientSingleton.instance) {
PrismaClientSingleton.instance = new PrismaClient()
}
return PrismaClientSingleton.instance
}
}
export default PrismaClientSingleton
سناریوی عملی دوم
سناریوی عملی دیگری که ما از آن عبور خواهیم کرد، یک سناریوی است سرویس محدود کننده نرخ درون حافظه.
کاربران یا هکرها میتوانند یک نقطه پایانی خاص را با درخواستهای فراوان به آن اسپم کنند. این می تواند منجر به آسیب پذیری ها، هزینه های غیرمنتظره یا خرابی سرور شود.
برای جلوگیری از آن، میتوانیم یک سرویس محدودکننده نرخ درون حافظه را پیادهسازی کنیم.
این سرویس باید تعداد درخواستها را محدود کند IP آدرس برای یک بازه زمانی خاص (مثلاً 60 ثانیه).
class RateLimiterService {
private static instance: RateLimiterService
private requests: Map
private readonly limit: number // Maximum number of requests
private readonly window: number // Time window in milliseconds
private constructor(limit: number = 5, window: number = 60000) {
this.requests = new Map()
this.limit = limit
this.window = window
}
// Method to get a unique singleton instance
public static getInstance(): RateLimiterService {
if (!RateLimiterService.instance) {
RateLimiterService.instance = new RateLimiterService()
}
return RateLimiterService.instance
}
public isRateLimited(ip: string): boolean {
const currentTime = Date.now()
const userRequestData = this.requests.get(ip)
if (userRequestData) {
const isExpired =
currentTime - userRequestData.lastRequestTime > this.window
if (isExpired) {
userRequestData.count = 1
userRequestData.lastRequestTime = currentTime
return false
} else {
userRequestData.count++
if (userRequestData.count > this.limit) {
return true
}
return false
}
} else {
this.requests.set(ip, { count: 1, lastRequestTime: currentTime })
return false
}
}
}
export default RateLimiterService
را RateLimiterService
کلاس نقشه ای را ذخیره می کند که تعداد درخواست ها را ردیابی می کند (requests[ip].count
) ساخته شدن توسط یک کاربر خاص که توسط یک شناسایی شده است آدرس IP (کلید نقشه) در یک پنجره زمان بندی داده شده (requests[ip].lastRequestTime
).
ما RateLimiterService
قرار است به صورت جهانی مورد استفاده قرار گیرد، یا به عبارت دیگر، ما نمی خواهیم مقادیر حالت داخلی متشکل از requests
نقشه، limit
، و window
متغیرها هر بار RateLimiterService
وارد می شود
نتیجه گیری
را الگوی طراحی Singleton یک ابزار قدرتمند برای مدیریت موثر منابع مشترک در برنامه های ما است
خوراکی های کلیدی:
- Singleton تضمین می کند که یک کلاس فقط یک نمونه دارد و یک نقطه دسترسی جهانی به آن فراهم می کند.
- برای مدیریت منابع مشترک مانند اتصالات پایگاه داده، تنظیمات پیکربندی یا حافظه پنهان مفید است.
- کاربردهای عملی شامل بهینه سازی ارتباطات پایگاه داده با ORMهایی مانند Prisma و پیاده سازی خدمات محدود کننده نرخ است.
تماس بگیرید
اگر سوالی دارید یا می خواهید در مورد چیزی بیشتر بحث کنید، با من در اینجا تماس بگیرید.
کد نویسی مبارک!