OCTOBER 24, 2024

Toshpo’latov Javoxir

Chain of Responsibility nima? Keling bu savolga javob topishdan avval bizda nima muammo bor va uni bu design patternsiz amalga oshira olmaymiz yoki amalga oshirsak ham juda murakkab bo’lib ketadi. Aytaylik biz turli xil kompaniyalar o’zining Parol validatsiyasini(PasswordPolicy) ishlab chiqish uchun foydalanadigan servis qilmoqchimiz. Masalan bazi saytlar parol 10 ta belgidan kam bo’lmasligini va kamida 2 ta maxsus belgilardan (@ , _ , #) iborat bo’lishini talab qilsa va bazilari raqamlardan iborat bo’lmasligini talab qiladi. Buni amalga oshirish uchun har bir validatsiyani if else lar orqali qilsak ichma-ich if else lar bo’lib ketadi va har bir kampaniya uchun alohida validatsiya qilishimizni inobatga oladigan bo’lsak kodimiz ancha murakkab bo’lib ketishi mumkin. Shu yerda bizga chain of responsibility design pattern yordamga keladi.

Chain of responsibility - bu keladigan ma’lum bir talab yoki so’rovni bir nechta handlerlar orqali ko’rib chiqish imkoni beruvchi design pattern hisoblanadi. Ya’ni tasavvur qiling sizda bir nechta ishchilar bor va ularning har birida o’zining alohida ishi va bu ishchilarning ketma-ketligi bor. Siz aytaylik bir ish buyurdingiz: Masalan biror mavzu bo’yicha savol berdingiz va sizning ishchilaringiz bu mulohozani ketma-ketlikda tekshirib chiqadi. Masalan 1-ishchi o’z vazifasi bo’yicha tekshiradi va agar javob topa olsa birdaniga sizga javob keladi ammo u bu so’rovni tekshira olmasa toki qisman tekshirsa qolgan qismini 2-ishchiga jo’natadi. Shu ketma-ketlikda so’rovimiz ishchilar orasida davom etadi. Va qaysi bir ichshi bu savolga to’liq javob topa olsa shu ishchida savol to’xtab sizga javobi qaytadi. Siz ishchilar ketma-ketligini o’zingiz xohlagandek belgilashingiz mumkin.

image.png

Endi keling yanada yaxshiroq tushunish uchun tepadagi misolni ko’rib o’tamiz.

Biz bitta IPasswordPolicy degan interfeys ochamiz va har bir validatsiyani yaratish uchun shu interfeysdan inheretence olgan classlar yaratamiz. Bu interfeysda CanHandle(string password) degan metod bo’ladi ya’ni bu metod kelayotgan parolni validatsiyadan o’tkazadi va agar bu validatsiyadan o’ta olsa true aks holda false qaytaradi. Shuningdek bu interfeysda SetNext( ) metodini ham ochamiz . Bu metodning vazifasi bu validatsiydan keyingi validatsiyani belgilab ketadi va shu orqali hamma validatsiyamiz bir biriga bog’lanadi (chain) va biz ularni xohlagan tartibda bog’lashimiz mumkin.

image.png

Quyidagi har bir class ning ichida CanHandle metodini implement qilishimiz kerak va bu implementni har bir class vazifasiga qarab amalga oshiramiz.

Minimum n ta belgi bo’lish validatsiyasi:

public class MinLenthHandler : PasswordHandler
{
    private readonly int _minLentgth;
    public MinLenthHandler(int minLength)
    {
        _minLentgth = minLength;
    }
    public override bool CanHandle(string password)
    {
        if (password.Length < _minLentgth)
        {
            Console.WriteLine($"Parol kamida {_minLentgth} ta belgidan iborat bo'lishi kerak");
            return false;
        }
        if (_next!=null)
            _next.CanHandle(password);
        return true;
    }
}

Raqam bo’lmaslik validatsiyasi

public class NoDigitHandler : PasswordHandler
{
    public override bool CanHandle(string password)
    {
        if (password.Any(char.IsDigit))
        {
            Console.WriteLine("Parolda raqamlar bo‘lmasligi kerak.");
            return false;
        }

        if (_next != null)
        {
            return _next.CanHandle(password);
        }

        return true;
    }
}

Kamida n ta maxsus belgidan iborat bo’lish validatsiyasi:

public class SpecialCharacterHandler : PasswordHandler
{
    private readonly int _minSpecialChars;
    private readonly char[] _specialChars = { '@', '#', '_', '!' };

    public SpecialCharacterHandler(int minSpecialChars)
    {
        _minSpecialChars = minSpecialChars;
    }

    public override bool CanHandle(string password)
    {
        int specialCharCount = password.Count(c => _specialChars.Contains(c));

        if (specialCharCount < _minSpecialChars)
        {
            Console.WriteLine($"Parol kamida {_minSpecialChars} maxsus belgilarni o‘z ichiga olishi kerak.");
            return false;
        }

        if (_next != null)
        {
            return _next.CanHandle(password);
        }

        return true;
    }
}

Har bir class ni vazifasiga qarab implement qilib chiqdik. Endi har bir foydalanuvchi uzini parol siyosatini ishlab chiqishda xohlagan ko’rinishda foydalanish mumkin. Zanjirni yani ketma ketlikni o’zi xohlagancha qilishi mumkin.