الگوی طراحی استراتژی با بوت فنری + کاتلین – کد پاک کننده بدون صفحه دیگ

اگر از قبل الگوی استراتژی را میدانید، کافی است به اینجا بروید.
چیست؟
طبق ویکی پدیا، الگوی استراتژی یک الگوی طراحی نرم افزار رفتاری است که امکان انتخاب یک الگوریتم را در زمان اجرا فراهم می کند. به جای اجرای مستقیم یک الگوریتم واحد، کد دستورالعملهای زمان اجرا را دریافت میکند که در خانوادهای از الگوریتمها استفاده شود.
به عبارت ساده، الگوی استراتژی برای مشخص کردن نحوه انجام کاری با ارائه یک الگوریتم خاص استفاده می شود.
به عنوان مثال، یک استراتژی برای پرداخت می تواند کارت اعتباری، پی پال یا هر ارائه دهنده پرداخت دیگری باشد.
چرا باید از آن استفاده کنیم؟
الگوی استراتژی خانواده ای از الگوریتم ها را تعریف می کند، هر کدام را کپسوله می کند و آنها را قابل تعویض می کند. استراتژی به الگوریتم اجازه می دهد مستقل از مشتریانی که از آن استفاده می کنند (منبع) متفاوت باشد.
به طور خلاصه، کد ما را پاکتر، نگهداری آسانتر و قابل استفاده مجدد میکند.
پیاده سازی الگو شامل یک رابط است که استراتژی را تعریف می کند، چندین پیاده سازی ملموس استراتژی و زمینه ای که از استراتژی استفاده می کند.
مثال کد
بیایید به سناریوی ساده شده زیر نگاه کنیم:
- ما یک برنامه کاربردی با کاربران داریم و باید کدهای تأیید 2FA را برای آنها ارسال کنیم.
- این برنامه از چندین گزینه ارتباطی برای دریافت کد تأیید پشتیبانی می کند: ایمیل، پیامک، اعلان ها …
- هر کاربر روش ارتباطی دلخواه خود را انتخاب می کند.
ابتدا رابط استراتژی خود را تعریف می کنیم:
interface VerificationCodeCommunicationStrategy {
fun sendVerificationCode(user: User, code: String)
}
حالا بیایید پیاده سازی های خود را اضافه کنیم:
class EmailCommunicationStrategy : VerificationCodeCommunicationStrategy {
override fun sendVerificationCode(user: User, code: String) {
emailClient.sendEmail(user.email, "Verification code", "Your verification is $code.")
}
}
class SmsCommunicationStrategy : VerificationCodeCommunicationStrategy {
override fun sendVerificationCode(user: User, code: String) {
smsClient.sendSMS(user.phone, "Your verification is $code.")
}
}
// ...
تنها چیزی که باقی می ماند استفاده از استراتژی است.
enum class CommunicationMethod {
Email, SMS, Notification
}
class VerificationCodeService {
val verificationCodeStrategyMap: Map<CommunicationMethod, VerificationCodeCommunicationStrategy> = mapOf(
CommunicationMethod.Email to EmailCommunicationStrategy(),
CommunicationMethod.SMS to SmsCommunicationStrategy(),
// ...
)
fun sendVerificationCode(user: User) {
val code = generateVerificationCode()
val verificationCodeStrategy = verificationCodeStrategyMap[user.preferredCommunicationMethod]
verificationCodeStrategy?.sendVerificationCode(user, code)
}
}
ما می توانیم ببینیم که چگونه کد تمیز است و نگهداری آن آسان است. افزودن یک روش ارتباطی جدید آسان خواهد بود و نیازی به تغییر کد موجود به جز افزودن آن به نقشه استراتژی ها نخواهد بود.
ما از الگوی استراتژی a-looot در پروژه های خود استفاده می کنیم. علاوه بر این، مانند همه توسعه دهندگان ما تنبل هستیم و می خواهیم زندگی خود را تا حد امکان آسان کنیم. به همین دلیل است که ما کتابخانه خود را ایجاد کردیم.
مثال کد بدون کتابخانه
بیایید مثال قبلی را برای اجرای معمولی Spring Boot بازبینی کنیم.
هنگام استفاده از الگوی استراتژی در برنامه Spring Boot، زمینه و پیاده سازی استراتژی معمولا اجزای Spring هستند.
ما با استراتژی ها شروع می کنیم:
interface VerificationCodeCommunicationStrategy {
fun sendVerificationCode(user: User, code: String)
}
@Component
class EmailCommunicationStrategy : VerificationCodeCommunicationStrategy {
override fun sendVerificationCode(user: User, code: String) {
emailClient.sendEmail(user.email, "Verification code", "Your verification is $code.")
}
}
@Component
class SmsCommunicationStrategy : VerificationCodeCommunicationStrategy {
override fun sendVerificationCode(user: User, code: String) {
smsClient.sendSMS(user.phone, "Your verification is $code.")
}
}
// ...
رابط ثابت می ماند و پیاده سازی ها را دریافت می کنند @Component
حاشیه نویسی
حالا بیایید به سمت سرویس تأیید حرکت کنیم.
@Service
class VerificationCodeServiceImpl(
private val emailCommunicationStrategy: EmailCommunicationStrategy,
private val smsCommunicationStrategy: SmsCommunicationStrategy
) {
private val verificationCodeStrategyMap: Map<CommunicationMethod, VerificationCodeCommunicationStrategy> = mapOf(
CommunicationMethod.Email to emailCommunicationStrategy,
CommunicationMethod.SMS to smsCommunicationStrategy
)
fun sendVerificationCode(user: User) {
val code = generateVerificationCode()
val verificationCodeStrategy = verificationCodeStrategyMap[user.preferredCommunicationMethod]
verificationCodeStrategy?.sendVerificationCode(user, code)
}
}
باید پیاده سازی های استراتژی را به سازنده اضافه کنیم و نقشه را به صورت دستی بسازیم. این جالب نیست!
مثال کد با کتابخانه
تمام هدف کتابخانه این است که زندگی ما را آسانتر کند و کد را پاکتر و کمتر مستعد اشکال کند. این کار را با ساختن نقشه استراتژی به صورت خودکار انجام می دهد.
ما با تغییر رابط استراتژی شروع خواهیم کرد.
interface VerificationCodeCommunicationStrategy {
@get:ComponentMapKey
val method: CommunicationMethod
fun sendVerificationCode(user: User, code: String)
}
همانطور که می بینید ما یک فیلد جدید اضافه کرده ایم method
با حاشیه نویسی @ComponentMapKey
. این به کتابخانه اطلاع می دهد که کدام فیلد کلید نقشه استراتژی است.
بیایید پیاده سازی ها را با توجه به رابط تغییر یافته به روز کنیم.
@Component
class EmailCommunicationStrategy : VerificationCodeCommunicationStrategy {
override val method = CommunicationMethod.Email
override fun sendVerificationCode(user: User, code: String) {
emailClient.sendEmail(user.email, "Verification code", "Your verification is $code.")
}
}
@Component
class SmsCommunicationStrategy : VerificationCodeCommunicationStrategy {
override val method = CommunicationMethod.SMS
override fun sendVerificationCode(user: User, code: String) {
smsClient.sendSMS(user.phone, "Your verification is $code.")
}
}
// ...
حالا بیایید سرویس را برای استفاده از کتابخانه تغییر دهیم.
@Service
class VerificationCodeServiceImpl {
@ComponentMap
private lateinit var verificationCodeStrategyMap: Map<CommunicationMethod, VerificationCodeCommunicationStrategy>
fun sendVerificationCode(user: User) {
val code = generateVerificationCode()
val verificationCodeStrategy = verificationCodeStrategyMap[user.preferredCommunicationMethod]
verificationCodeStrategy?.sendVerificationCode(user, code)
}
}
خودشه! تنها کاری که باید انجام میدادیم این بود که آن را اضافه کنیم @ComponentMap
حاشیه نویسی به نقشه استراتژی و voila! نقشه به طور خودکار از اجزای سازنده ساخته می شود. بدون کد دیگ بخار برای افزودن یک استراتژی جدید تنها کاری که باید انجام دهید این است که یک پیاده سازی جدید ایجاد کنید و به صورت “جادویی” به تمام نقشه های استراتژی مرتبط اضافه می شود.
این کتابخانه پر استفاده ترین کتابخانه در پروژه های ما است. اگرچه این تغییر زندگی نیست، فقط مفید است، به ما کمک می کند کد خود را تمیز نگه داریم و از فراموش کردن بسیاری از باگ های تکرار شونده برای اضافه کردن استراتژی های جدید به نقشه های مناسب خود جلوگیری می کند.
اگر مایل به استفاده از آن هستید، می توانید با راهنمای شروع سریع شروع کنید.
ما منبع باز را توسعه می دهیم زیرا آن را دوست داریم و می خواهیم در این امر سهیم باشیم. اگر می خواهید از ما حمایت کنید، لطفاً مخزن را ستاره دار کنید.