ساختی ڈیزائن کے نمونے اس بات سے نمٹتے ہیں کہ ساخت اور درجہ بندی کے لحاظ سے اشیاء کی تخلیق کیسے کی جاتی ہے۔
ایک نمونہ جو واضح طور پر پیچیدہ درجہ بندی کے منظرناموں کو منظم کرنے میں مدد کرتا ہے جامع ڈیزائن پیٹرن ہے۔
تو یہ پیٹرن اصل میں کیا کرتا ہے؟
میں آپ کو ایک مثال دیتا ہوں۔ آپ کے پاس ڈیٹا سیٹس ہیں اور آپ ان ڈیٹا سیٹس کو منظم کرنے کے لیے ایک مشترکہ انٹرفیس چاہتے ہیں، لہذا ہر چیز کے لیے ایک طریقہ ہے۔ ہم یہ بھی چاہتے ہیں کہ بلیو پرنٹ اس ڈیٹا کا نظم کرے اور اسے زیادہ سے زیادہ بڑھنے کی اجازت دے۔ یہ آبجیکٹ کمپوزیشن کے جامع ڈیزائن پیٹرن کے لیے بہترین فٹ ہے۔
یہاں کچھ دیگر واضح استعمال کے معاملات ہیں:
-
آپ کی خریداری کی ٹوکری انفرادی اشیاء پر مشتمل ہے۔ کچھ اشیاء ایک ساتھ فروخت کی جاتی ہیں۔ دونوں کو قیمت درکار ہے۔
-
ٹیکس نظام میں انفرادی ٹیکس دہندگان ہیں۔ فیملی گروپس اور کارپوریٹ گروپس بھی ہیں۔ تمام آئٹمز پر ٹیکسوں کا حساب لگانے، چھوٹ لاگو کرنے اور سال بہ تاریخ کے کل حساب کی ضرورت ہوتی ہے۔
-
ایک فائل سسٹم انفرادی فائلوں پر مشتمل ہے۔ ایسے فولڈرز بھی ہیں جن میں فائلیں یا دوسرے فولڈر ہوتے ہیں۔ دونوں کو سائز کی ضرورت ہے۔
ایک سادہ طریقہ یہ ہوگا کہ افراد اور گروہوں کے لیے الگ الگ منطق لکھیں، پھر ٹائپ چیکنگ شامل کریں جہاں آپ کو دونوں کو سنبھالنے کی ضرورت ہے۔ لیکن منطق مختلف ہے۔ ٹائپ چیک ضرب۔ اور کسی بھی نئے کام کا مطلب دونوں شاخوں کو اپ ڈیٹ کرنا ہے۔ آپ کا کوڈ بڑھانا مشکل اور بھروسہ کرنا مشکل ہو جاتا ہے۔
جامع ڈیزائن پیٹرن اسے مکمل طور پر ختم کرتا ہے۔ ایک مشترکہ انٹرفیس کی وضاحت کرتا ہے جسے انفرادی اشیاء اور گروہ دونوں نافذ کرتے ہیں۔ کالنگ کوڈ قسم کی جانچ نہیں کرتا ہے۔ ایک ہی طریقہ کو کسی پتی یا مرکب پر کال کریں اور دونوں طرح سے صحیح نتیجہ حاصل کریں۔
انڈیکس
شرائط
اس مضمون کو پڑھنے سے پہلے، آپ کو درج ذیل سے واقف ہونا چاہیے:
-
آبجیکٹ پر مبنی پروگرامنگ: خلاصہ کلاسز، انٹرفیسز، اور وراثت
-
تصوراتی سطح پر ڈیزائن پیٹرن کیا ہے؟
-
بنیادی ڈارٹ یا C# نحو
ساختی ڈیزائن کے نمونوں کے ساتھ کسی پیشگی تجربے کی ضرورت نہیں ہے۔ یہ مضمون حقیقی پیداوار کی مثالوں کے ذریعے پہلے اصولوں کے جامع نمونوں کو متعارف کرایا گیا ہے۔
ایک جامع ڈیزائن پیٹرن کیا ہے؟
جامع ڈیزائن پیٹرن ایک ساختی ڈیزائن پیٹرن ہے. تخلیق کے نمونے اس بات سے نمٹتے ہیں کہ اشیاء کی تخلیق کیسے کی جاتی ہے، طرز عمل کے نمونے اس بات سے نمٹتے ہیں کہ اشیاء کیسے بات چیت کرتی ہیں، جبکہ ساختی نمونے اس بات سے نمٹتے ہیں کہ اشیاء کو کس طرح منظم اور ایک دوسرے سے منسلک کیا جاتا ہے۔
جامع پیٹرن خاص طور پر جزوی مکمل درجہ بندی سے نمٹتے ہیں۔ یہ آپ کو اشیاء کو درخت کے ڈھانچے میں ترتیب دینے اور پھر اس درخت کے ساتھ اس طرح کام کرنے کی اجازت دیتا ہے جیسے درخت کے تمام نوڈس ایک ہی قسم کے ہوں۔
بنیادی خیال دھوکہ دہی سے آسان ہے۔ ایک مشترکہ انٹرفیس کی وضاحت کریں، انفرادی اشیاء سے اس پر عمل درآمد کریں، اور اشیاء کے گروپس کو بھی اس پر عمل درآمد کریں۔ اب درجہ بندی میں ہر چیز ایک ہی طریقہ پر جواب دیتی ہے، اور کالنگ کوڈ کو پتیوں اور مرکبات کے درمیان فرق کرنے کی ضرورت نہیں ہے۔
اس کا اصل مطلب کیا ہے "ایک متحد انٹرفیس کے ذریعے انفرادی اشیاء اور گروہوں پر کارروائی کرنا۔” سنگل میتھڈ کال، قطع نظر اس سے کہ آپ اسے کسی ایک آئٹم پر کال کریں یا سیکڑوں آئٹمز پر مشتمل نیسٹڈ گروپ پر، درجہ بندی میں کسی بھی چیز پر آپ کو صحیح نتیجہ ملے گا۔
تین تہوں
ایک جامع پیٹرن میں تین الگ الگ پرتیں ہوتی ہیں: کوڈ کو دیکھنے سے پہلے ہر ایک کو سمجھنے سے عمل درآمد زیادہ واضح ہوجائے گا۔
اجزاء کی پرت
یہ ایک تجریدی کلاس یا انٹرفیس ہے جو درجہ بندی میں تمام اشیاء کے معاہدے کی وضاحت کرتا ہے۔ ان طریقوں کا اعلان کرتا ہے جو انفرادی اشیاء اور گروہوں دونوں کو لاگو کرنا ضروری ہے۔
اجزاء یکساں پروسیسنگ کو اہل بناتے ہیں۔ چونکہ درجہ بندی میں ہر چیز اس انٹرفیس کو نافذ کرتی ہے، ہر چیز اسی طریقہ کال کا جواب دیتی ہے۔
پتیوں کی پرت
ایک پتی ایک جزو کا ٹھوس نفاذ ہے۔ یہ ایک ایسی انفرادی چیز کی نمائندگی کرتا ہے جس کے کوئی بچے نہیں ہیں، جیسے کہ شاپنگ کارٹ میں ایک ہی چیز، ایک ٹیکس دہندہ، یا ایک فائل۔ لیف اجزاء کے طریقوں کو اپنی مخصوص منطق کے ساتھ نافذ کرتا ہے۔
جامع پرت
کمپوزٹ بھی اجزاء کا ایک ٹھوس نفاذ ہے۔ تاہم، لیف کے برعکس، اس میں بچوں کا مجموعہ ہوتا ہے۔ ہر بچہ ایک جزو ہے۔ یعنی ہر بچہ ایک پتی یا دوسری پیچیدہ چیز ہو سکتا ہے۔
کمپوزٹ اپنے بچوں کو تفویض کرکے اور نتائج کو جمع کرکے اجزاء کے طریقوں کو لاگو کرتا ہے۔
ان تہوں کے درمیان تعلقات درخت کی ساخت اور یکساں انٹرفیس دونوں کو قابل بناتے ہیں۔
خریداری کی ٹوکری کو قیمت کا حساب لگانا چاہیے۔ انفرادی اشیاء کی اپنی قیمتیں ہوتی ہیں۔ ایک بنڈل متعدد اشیاء کو گروپ کرتا ہے اور قیمت ان کے مواد کا مجموعہ ہے۔ دونوں کو جواب دینا چاہیے۔ getPrice().
جزو
abstract class PriceComponent {
double getPrice();
}
PriceComponent یہ ایک معاہدہ ہے۔ شاپنگ کارٹ کے درجہ بندی میں تمام اشیاء کو لاگو کرنا ضروری ہے: getPrice(). یہ پورا انٹرفیس ہے۔ ایک طریقہ جو تمام اشیاء میں یکساں ہے۔
پتی
class CartItem extends PriceComponent {
final int id;
final String name;
final double price;
CartItem({required this.id, required this.name, required this.price});
@override
double getPrice() {
return price;
}
}
CartItem یہ ایک پتی ہے۔ آپ کی خریداری کی ٹوکری میں ایک آئٹم کی نمائندگی کرتا ہے۔ کہ getPrice() یہ براہ راست اپنی قیمت واپس کرتا ہے۔ کوئی مندوبین یا بچے نہیں ہیں۔ یہ اپنے آپ میں صرف ایک قدر ہے۔
پیچیدہ
class ItemBundle extends PriceComponent {
final int bundleId;
final String bundleName;
final List _items = [];
ItemBundle({required this.bundleId, required this.bundleName});
void add(PriceComponent component) {
_items.add(component);
}
void remove(PriceComponent component) {
_items.remove(component);
}
@override
double getPrice() {
return _items.fold(0, (total, item) => total + item.getPrice());
}
}
ItemBundle یہ ایک جامع ہے۔ ہمارے پاس درج ذیل فہرست ہے: PriceComponent بچے۔ کہ getPrice() یہ استعمال کرتے ہوئے اولاد کو تفویض کریں: foldخلاصہ کریں کہ ہر بچہ کیا واپس کرتا ہے۔
اہم تفصیلات: _items ہے Listنہیں List. اس کا مطلب ہے: ItemBundle دونوں پر مشتمل ہو سکتا ہے۔ CartItem پتے اور دیگر ItemBundle مرکبات درجہ بندی کو ضرورت کے مطابق گہرائی سے بنایا جاسکتا ہے۔
اس کا استعمال کرتے ہوئے
void main() {
final burger = CartItem(id: 1, name: 'Burger', price: 5.99);
final fries = CartItem(id: 2, name: 'Fries', price: 2.99);
final drink = CartItem(id: 3, name: 'Drink', price: 1.99);
final apple = CartItem(id: 4, name: 'Apple', price: 0.99);
final comboMeal = ItemBundle(bundleId: 1, bundleName: 'Combo Meal');
comboMeal
..add(burger)
..add(fries)
..add(drink);
final cart = ItemBundle(bundleId: 0, bundleName: 'My Cart');
cart
..add(comboMeal)
..add(apple);
// same method call on everything
print('Burger: \$${burger.getPrice()}');
print('Combo Meal: \$${comboMeal.getPrice()}');
print('Full Cart: \$${cart.getPrice()}');
}
burger.getPrice() لیف کے نفاذ کو براہ راست کال کرتا ہے۔ comboMeal.getPrice() یہ ایک جامع نفاذ کو کہتے ہیں جو تین بچوں کو تفویض کرتا ہے۔ cart.getPrice() ڈیلیگیٹنگ کمپوزٹ نفاذ کو کہتے ہیں۔ combo meal جامع اور apple پتی
کالنگ کوڈ تمام اشیاء کے ساتھ یکساں سلوک کرتا ہے۔ getPrice()نتیجہ، مکمل۔
حقیقی زندگی کی مثال 2: ٹیکس کا انتظام
یہ مثال زیادہ پیچیدہ ڈومین پر لاگو ایک جامع نمونہ دکھاتی ہے۔ ٹیکس کے انتظام کے نظام کو ٹیکس کی رقم کا حساب لگانا چاہیے، چھوٹ کا اطلاق کرنا چاہیے، اور سال بہ تاریخ کا حساب لگانا چاہیے۔ ان حسابات کو انفرادی ٹیکس دہندگان اور ٹیکس دہندگان کے گروپوں کے لیے بالکل ایک ہی انٹرفیس کے ذریعے کام کرنا چاہیے۔
جزو
abstract class TaxManager {
num getTaxAmount();
num getTaxDiscount();
num getTotalTaxYTD();
}
TaxManager ہم تین طریقوں کی وضاحت کرتے ہیں: ٹیکس کی تہہ میں موجود تمام اشیاء کو تینوں کو لاگو کرنا چاہیے۔ ایک ٹیکس دہندہ اسے اپنے ڈیٹا سے لاگو کرتا ہے۔ گروپس تمام اراکین کو جمع کر کے اس پر عمل درآمد کرتے ہیں۔ کالنگ کوڈ ان طریقوں کو ہر چیز پر کال کرتا ہے اور صحیح نتیجہ حاصل کرتا ہے۔
پتی
class SingleUser extends TaxManager {
final num _amount;
final List _allTaxes;
SingleUser(this._amount, this._allTaxes);
@override
num getTaxAmount() {
return _amount;
}
@override
num getTaxDiscount() {
return _amount % 2 == 0 ? _amount : (_amount / 2);
}
@override
num getTotalTaxYTD() {
num total = 0;
for (final tax in _allTaxes) {
total += tax;
}
return total;
}
}
SingleUser یہ ایک پتی ہے۔ یہ ایک انفرادی ٹیکس دہندہ کی نمائندگی کرتا ہے۔ _amount یہ موجودہ ٹیکس کی رقم ہے۔ _allTaxes یہ سالانہ ٹیکس ادائیگیوں کی فہرست ہے۔ ہر طریقہ صرف اس شخص کے ڈیٹا پر لاگو ہوتا ہے۔
getTaxDiscount() سادہ رعایتی قوانین لاگو ہوتے ہیں۔ یکساں نمبر والی رقم پوری رقم وصول کرتی ہے، طاق نمبر والی رقم نصف وصول کرتی ہے۔ یہ اصول ایک فرد پر لاگو ہوتا ہے اور خود بخود ان تمام گروپس کے ذریعے پھیلتا ہے جن میں یہ صارف شامل ہے۔
getTotalTaxYTD() صارف کی گزشتہ ٹیکس ادائیگیوں کو سال سے تاریخ کے کل کا حساب لگانے کے لیے شامل کیا جاتا ہے۔
پیچیدہ
class UserGroup extends TaxManager {
final String groupName;
final List _members = [];
UserGroup(this.groupName);
void add(TaxManager member) {
_members.add(member);
}
void remove(TaxManager member) {
_members.remove(member);
}
@override
num getTaxAmount() {
return _members.fold(0, (total, member) => total + member.getTaxAmount());
}
@override
num getTaxDiscount() {
return _members.fold(0, (total, member) => total + member.getTaxDiscount());
}
@override
num getTotalTaxYTD() {
return _members.fold(0, (total, member) => total + member.getTotalTaxYTD());
}
}
UserGroup یہ ایک جامع ہے۔ ہمارے پاس درج ذیل فہرست ہے: TaxManager رکن ہر طریقہ تمام ممبروں کو تفویض کرتا ہے اور نتائج کو ختم کرتا ہے۔
توجہ فرمائیں _members یہ درج ذیل ہے: Listنہیں List. اس کا مطلب ہے: UserGroup افراد شامل ہو سکتے ہیں۔ SingleUser پتے یا دیگر UserGroup مرکبات فیملی گروپ انفرادی ممبران پر مشتمل ہو سکتا ہے۔ کمپنی گروپس میں فیملی گروپس شامل ہو سکتے ہیں۔ درجہ بندی ضرورت کے مطابق بڑھ سکتی ہے اور انٹرفیس کبھی تبدیل نہیں ہوتا ہے۔
اس کا استعمال کرتے ہوئے
void main() {
final seyisTax = SingleUser(100000, List.generate(12, (_) => 20000));
final ronkesTax = SingleUser(5000, List.generate(12, (_) => 50000));
final inisTax = SingleUser(20000, List.generate(12, (_) => 20000));
final tiwasTax = SingleUser(10000, List.generate(12, (_) => 10000));
print('Seyi tax amount: ${seyisTax.getTaxAmount()}');
print('Ronke tax amount: ${ronkesTax.getTaxAmount()}');
print('Seyi discount: ${seyisTax.getTaxDiscount()}');
print('Seyi YTD: ${seyisTax.getTotalTaxYTD()}');
// build a family group
final fatunmoles = UserGroup('Fatunmoles');
fatunmoles
..add(seyisTax)
..add(ronkesTax)
..add(inisTax)
..add(tiwasTax);
print('Total tax: ${fatunmoles.getTaxAmount()}');
print('Total discount: ${fatunmoles.getTaxDiscount()}');
print('Total YTD: ${fatunmoles.getTotalTaxYTD()}');
// a second family group
final child1 = SingleUser(100000, List.generate(12, (_) => 20000));
final child2 = SingleUser(100000, List.generate(12, (_) => 20000));
final child3 = SingleUser(100000, List.generate(12, (_) => 20000));
final unknownFamily = UserGroup('UnknownFamily');
unknownFamily
..add(child1)
..add(child2)
..add(child3);
print('Tax: ${unknownFamily.getTaxAmount()}');
print('Discount: ${unknownFamily.getTaxDiscount()}');
print('YTD: ${unknownFamily.getTotalTaxYTD()}');
}
وہی تین طریقہ کار کام کریں گے۔ seyisTax (1 شخص) fatunmoles (4 افراد) اور unknownFamily (3 افراد)۔ کالنگ کوڈ ایک جیسا ہے۔ درجہ بندی کے ہر سطح کے لیے نتائج درست ہیں۔
نیسٹڈ کمپوزٹ کی طاقت
جامع پیٹرن کا سب سے طاقتور پہلو یہ ہے کہ مرکبات دیگر مرکبات پر مشتمل ہوسکتے ہیں۔ کوئی راستہ نہیں UserGroup دیگر مواد پر مشتمل ہو سکتا ہے۔ UserGroup اشیاء یہ تمام سطحوں پر یکساں، یکساں انٹرفیس کو برقرار رکھتے ہوئے گہری درجہ بندی کی اجازت دیتا ہے۔
void demonstrateNesting() {
final seyi = SingleUser(100000, List.generate(12, (_) => 20000));
final ronke = SingleUser(5000, List.generate(12, (_) => 50000));
final ini = SingleUser(20000, List.generate(12, (_) => 20000));
final tiwa = SingleUser(10000, List.generate(12, (_) => 10000));
final child1 = SingleUser(100000, List.generate(12, (_) => 20000));
final child2 = SingleUser(100000, List.generate(12, (_) => 20000));
final child3 = SingleUser(100000, List.generate(12, (_) => 20000));
// family groups
final fatunmoles = UserGroup('Fatunmoles');
fatunmoles
..add(seyi)
..add(ronke)
..add(ini)
..add(tiwa);
final unknownFamily = UserGroup('UnknownFamily');
unknownFamily
..add(child1)
..add(child2)
..add(child3);
// a composite that contains other composites
// both families treated as one unit
final allFamilies = UserGroup('AllFamilies');
allFamilies
..add(fatunmoles)
..add(unknownFamily);
// same interface, now covers all 7 people across both families
print('All families combined:');
print('Total tax: ${allFamilies.getTaxAmount()}');
print('Total discount: ${allFamilies.getTaxDiscount()}');
print('Total YTD: ${allFamilies.getTotalTaxYTD()}');
}
allFamilies.getTaxAmount() پورے درخت کو عبور کریں: پوچھیں: fatunmoles چار ممبران میں سے ہر ایک سے پوچھیں، unknownFamily یہ تینوں اراکین میں سے ہر ایک سے پوچھے گئے کل ہیں۔ 7 لوگ، 1 طریقہ کال۔ کال کرنے والا یہ نہیں جانتا کہ درخت کتنا گہرا ہے یا کسی خاص سطح پر کتنے ارکان موجود ہیں۔
یہ وہ جگہ ہے جہاں پیٹرن اپنی سب سے بڑی قدر ظاہر کرتے ہیں۔ آپ محکموں، ڈویژنوں، ٹیموں اور افراد پر مشتمل ایک تنظیم بنا سکتے ہیں، سبھی ایک جیسی فعالیت کو نافذ کرتے ہیں۔ TaxManager انٹرفیس اور کالز getTaxAmount() اگر آپ اپنی تنظیم میں ہر ایک کے لیے ٹوٹل حاصل کرنا چاہتے ہیں، تو ایک محکمہ کو کال کریں۔ یا ایک شخص کو کال کریں۔ انٹرفیس ہمیشہ ایک جیسا ہوتا ہے۔
C# میں مرکب پیٹرن
C# میں ایک ہی نمونہ ظاہر کرتا ہے کہ یہ ایک عالمگیر ساختی اصول ہے۔ ذیل میں کارپوریٹ پے رول سیاق و سباق کے لیے C# میں نقل کردہ ٹیکس مینجمنٹ سسٹم ہے۔
جزو
public interface ITaxManager
{
decimal GetTaxAmount();
decimal GetTaxDiscount();
decimal GetTotalTaxYTD();
}
پتی
public class Employee : ITaxManager
{
private readonly string _name;
private readonly decimal _taxAmount;
private readonly List _yearlyTaxes;
public Employee(string name, decimal taxAmount, List yearlyTaxes)
{
_name = name;
_taxAmount = taxAmount;
_yearlyTaxes = yearlyTaxes;
}
public decimal GetTaxAmount() => _taxAmount;
public decimal GetTaxDiscount()
{
return _taxAmount % 2 == 0 ? _taxAmount : _taxAmount / 2;
}
public decimal GetTotalTaxYTD()
{
return _yearlyTaxes.Sum();
}
}
پیچیدہ
public class Department : ITaxManager
{
private readonly string _name;
private readonly List _members = new();
public Department(string name)
{
_name = name;
}
public void Add(ITaxManager member) => _members.Add(member);
public void Remove(ITaxManager member) => _members.Remove(member);
public decimal GetTaxAmount()
{
return _members.Sum(m => m.GetTaxAmount());
}
public decimal GetTaxDiscount()
{
return _members.Sum(m => m.GetTaxDiscount());
}
public decimal GetTotalTaxYTD()
{
return _members.Sum(m => m.GetTotalTaxYTD());
}
}
اسے C# میں استعمال کرنا
var alice = new Employee("Alice", 150000, Enumerable.Repeat(25000m, 12).ToList());
var bob = new Employee("Bob", 80000, Enumerable.Repeat(15000m, 12).ToList());
var carol = new Employee("Carol", 120000, Enumerable.Repeat(20000m, 12).ToList());
var dave = new Employee("Dave", 95000, Enumerable.Repeat(18000m, 12).ToList());
var engineering = new Department("Engineering");
engineering.Add(alice);
engineering.Add(bob);
var design = new Department("Design");
design.Add(carol);
design.Add(dave);
var company = new Department("TechCorp");
company.Add(engineering);
company.Add(design);
Console.WriteLine($"Alice tax: {alice.GetTaxAmount()}");
Console.WriteLine($"Engineering total: {engineering.GetTaxAmount()}");
// entire company — traverses all departments and all employees
Console.WriteLine($"Company total tax: {company.GetTaxAmount()}");
Console.WriteLine($"Company total discount: {company.GetTaxDiscount()}");
Console.WriteLine($"Company YTD: {company.GetTotalTaxYTD()}");
ڈھانچہ ڈارٹ کے نفاذ سے مماثل ہے۔ ITaxManager یہ ایک جزو ہے۔ Employee یہ ایک پتی ہے، Department یہ ایک جامع ہے۔ درجہ بندی مندرجہ ذیل ہے: Department کی Departments ایک کمپنی بنائیں۔ کالنگ کوڈ درخت کے ہر نوڈ پر ایک ہی تین طریقوں کو کال کرتا ہے اور صحیح مجموعی نتیجہ حاصل کرتا ہے۔
یہ وہی نمونہ ہے جو دوسری زبان میں اسی مسئلے کو حل کرتا ہے۔ ساختی اصول عالمگیر ہیں۔
پیچیدہ پیٹرن کب استعمال کریں۔
جامع پیٹرن کا استعمال کریں جب آپ کے پاس جزوی مکمل درجہ بندی ہو جہاں دونوں حصوں اور پورے حصوں کو یکساں سلوک کیا جائے۔
یہ بھی ایک اچھا انتخاب ہے جب کالنگ کوڈ کو انفرادی اشیاء اور گروپوں کے درمیان فرق کرنے کی ضرورت نہیں ہے۔ اگر آپ یہ چیک کرنے کے لیے کثرت سے مشروط لکھتے ہیں کہ آیا کوئی شے ایک گروپ ہے یا ایک، تو یہ اس بات کی علامت ہے کہ Composite اس شاخ کو ہٹا رہا ہے۔
یہ اس وقت مفید ہوتا ہے جب درجہ بندی کو لچکدار اور گہرائی سے مستحکم ہونے کی ضرورت ہو۔ فائل سسٹمز، تنظیمی چارٹس، UI اجزاء کے درخت، زمرہ کے درجہ بندی، ٹیکس کے نظام، یا بنڈلز کے ساتھ شاپنگ کارٹس: کوئی بھی ڈومین جہاں کنٹینرز دوسرے کنٹینرز کو رکھ سکتے ہیں کمپوزٹ سے فائدہ اٹھا سکتے ہیں۔
اور یہ بعد میں نئی قسم کے پتے یا مرکبات شامل کرتے وقت مفید ہوگا۔ چونکہ ہر چیز ایک ہی اجزاء انٹرفیس کو نافذ کرتی ہے، ایک نئی قسم کی پتی (a CorporateTaxpayer پہلو بہ پہلو SingleUser) یا ایک نئی قسم کا مرکب (a TaxBracketGroup) کا مطلب ہے ایک نئی کلاس بنانا۔ کالنگ کوڈ اور تمام موجودہ کلاسز میں کوئی تبدیلی نہیں ہوئی ہے۔
کب استعمال نہ کریں۔
جامع استعمال نہ کریں جب تک کہ آپ کا درجہ بندی آسان اور اوورلیپ ہونے کا امکان نہ ہو۔ اگر آپ کے پاس انفرادی آئٹمز ہیں اور گھوںسلا کیے بغیر گروپ بندی کی بالکل ایک سطح ہے، تو پیٹرن تجرید کا اضافہ کرتا ہے جس کی ایک آسان اپروچ کی ضرورت نہیں ہے۔
اگر انفرادی اشیاء اور گروہوں کو واقعی مختلف انٹرفیس کی ضرورت ہو تو یہ بھی اچھا انتخاب نہیں ہے۔ اگر گروپوں کو بہت سے اضافی طریقوں کی ضرورت ہوتی ہے جن کی افراد کو بالکل ضرورت نہیں ہوتی ہے، تو انہیں ایک ہی انٹرفیس استعمال کرنے پر مجبور کرنے سے انٹرفیس بہت وسیع ہو جائے گا اور انٹرفیس علیحدگی کے اصول کی خلاف ورزی ہو گی۔
اس سے بچیں اگر کارکردگی اہم ہے اور بار بار آنے والے ٹراورسل کا اوور ہیڈ اہم ہے۔ لاکھوں بار بار چلنے والے نوڈس کے ساتھ گہری درجہ بندی ایک مختلف نقطہ نظر سے فائدہ اٹھا سکتی ہے: مجموعی نتائج کو کیش کرنا۔
نتیجہ
جامع ڈیزائن کے نمونے درجہ بندی کے نظام کے ساتھ بنیادی مسائل کو حل کرتے ہیں۔ میں انفرادی اشیاء اور اشیاء کے گروپس دونوں پر دو الگ الگ نفاذ لکھے یا ٹائپ چیکنگ کے ساتھ اپنے کوڈ کو بے ترتیبی کیے بغیر ایک ہی کام کیسے کروں؟
جواب ایک مشترکہ انٹرفیس ہے۔ درجہ بندی میں تمام اشیاء ایک ہی معاہدے کو نافذ کرتی ہیں۔ انفرادی ادارے اسے اپنے ڈیٹا سے نافذ کرتے ہیں۔ گروپ اپنے بچوں کو تفویض کرکے اور نتائج کو جمع کرکے اس پر عمل درآمد کرتا ہے۔ کالنگ کوڈ اسی طریقہ کو کال کرتا ہے اور اس سے قطع نظر کہ یہ کسی پتی سے بات کر رہا ہے یا گھوںسلا کی 100 سطحوں کے ساتھ جامع جواب دیتا ہے۔
خریداری کی ٹوکری کی مثال قیمتوں کے لیے درج ذیل دکھاتی ہے: getPrice() ایک ایسا طریقہ جو ایک ہی شے یا دوسرے بنڈل پر مشتمل بنڈل کے لیے یکساں طور پر کہا جاتا ہے۔ ٹیکس مینجمنٹ کی مثال متعدد کاموں والے ڈومین کے لیے درج ذیل دکھاتی ہے: getTaxAmount(), getTaxDiscount()اور getTotalTaxYTD() ایک ہی ٹیکس دہندہ، فیملی گروپ، یا فیملی گروپس کے مجموعے کے لیے بھی یہی کہا جاتا ہے۔
نیسٹڈ کمپوزٹ ڈیمو زیادہ سے زیادہ کارکردگی دکھاتا ہے۔ UserGroup دوسری چیزوں پر مشتمل ہے۔ UserGroupsہر ایک میں شامل ہیں: SingleUsersوہ سب ایک ہی انٹرفیس کا جواب دیتے ہیں اور تمام سطحوں پر درست مجموعی نتائج پیدا کرتے ہیں۔ 7 لوگ، 1 طریقہ کال۔ درخت خود بخود گزر جاتا ہے۔
C# کارپوریٹ پے رول سیاق و سباق میں انہی اصولوں کو ظاہر کرتا ہے۔ ملازمین ملازمین سے بنتے ہیں، محکمے مرکبات سے بنتے ہیں، اور کمپنیاں محکموں سے بنتی ہیں۔ ایک انٹرفیس، تمام درجہ بندی کی سطحیں۔ ہر بار صحیح نتائج حاصل کریں۔
جامع پیٹرن پیچیدگی کو ختم نہیں کرتے ہیں۔ اس پر مشتمل ہے۔ گہرے درجہ بندی میں نتائج کو جمع کرنے کی پیچیدگی جامع کے لیے اندرونی ہے۔ fold یہ پورے کالنگ کوڈ میں تقسیم نہیں ہوتا ہے۔ کالنگ کوڈ صاف رہتا ہے۔ درجہ بندی لچکدار رہتی ہے۔ آپ پہلے سے موجود چیزوں کو تبدیل کیے بغیر نئی اقسام شامل کر سکتے ہیں۔
یہ ساختی نظم و ضبط ہے جو جامع نمونے فراہم کرتے ہیں۔
مبارک کوڈنگ!