This project is set up for implementing and testing data structures in plain JavaScript.
npm start: run the entry file once.npm run dev: run the entry file in watch mode.npm test: run the test suite with Node's built-in test runner.npm run test:watch: rerun tests in watch mode.
Instead of creating objects directly, these patterns give you more flexibility in how objects come into existence.
Pattern files:
All Singleton details, examples, and diagrams are in docs/patterns/creational/singleton.md.
All Builder details and examples are in docs/patterns/creational/builder.md.
All Factory details and examples are in docs/patterns/creational/factory.md.
Deal with how objects relate to each other.
Think of them as blueprints for building larger structures from individual pieces.
Pattern files:
All Adapter details and examples are in docs/patterns/structural/adapter.md.
All Facade details and examples are in docs/patterns/structural/facade.md.
All Decorator details and examples are in docs/patterns/structural/decorator.md.
All Composite details and examples are in docs/patterns/structural/composite.md.
All Proxy details and examples are in docs/patterns/structural/proxy.md.
Handle communication between objects - how they interact and distribute responsibility.
Pattern files:
All Strategy details and examples are in docs/patterns/behavioral/strategy.md.
All Observer details and examples are in docs/patterns/behavioral/observer.md.
All Command details and examples are in docs/patterns/behavioral/command.md.
All State details and examples are in docs/patterns/behavioral/state.md.
شكل ثابت في دماغك لكل Pattern يعني صورة ذهنية بسيطة تحفظها، ولما تشوف مشكلة في الكود تقول: "آه ده محتاج كذا".
الصورة في دماغك: الملك الوحيد
تخيل مملكة فيها ملك واحد بس، وكل الناس بترجع له.
Application -> One shared instance
احفظها كده: Singleton = واحد فقط + وصول من أي مكان
مثال تحفظه:
- Logger واحد للتطبيق كله
- Config واحد للتطبيق كله
الجملة الذهبية: "أنا عايز نسخة واحدة بس من الحاجة دي."
الصورة في دماغك: طبق بيتعمل بوصفة
تخيل إنك بتعمل بيتزا أو سندوتش. تضيف جبنة، بعدين صوص، بعدين فراخ، بعدين تعمل build.
Start -> add option -> add option -> add option -> build final object
احفظها كده: Builder = بناء object خطوة بخطوة
مثال تحفظه:
new RequestBuilder()
.setUrl()
.setMethod()
.setHeaders()
.setBody()
.build();الجملة الذهبية: "الـ constructor بقى طويل ومقرف، خليني أبنيه خطوة خطوة."
الصورة في دماغك: مصنع بيطلع المنتج المناسب
تخيل مصنع. أنت تقول له: "عايز عربية SUV"، هو يطلعلك SUV. تقول له: "عايز Truck"، يطلعلك Truck.
type -> Factory -> correct object
احفظها كده: Factory = يختار وينشئ object المناسب
مثال تحفظه:
UserFactory.create("admin");
UserFactory.create("moderator");
UserFactory.create("regular");الجملة الذهبية: "أنا مش عايز أعمل new في كل حتة، المصنع يقرر."
الصورة في دماغك: زرار واحد وراه شغل كتير
تخيل زرار اسمه Buy Now. أنت ضغطت زرار واحد، بس وراه حصل:
- check stock
- payment
- fraud check
- create order
- send email
احفظها كده: Facade = واجهة بسيطة فوق نظام معقد
مثال تحفظه:
checkoutFacade.buyNow(order);الجملة الذهبية: "أنا عايز أخبي التعقيد ورا method بسيطة."
الصورة في دماغك: محوّل USB to HDMI
عندك حاجتين مش راكبين على بعض، فتحط بينهم Adapter.
Old/External API -> Adapter -> Your App Interface
احفظها كده: Adapter = يخلي حاجتين مش متوافقين يشتغلوا مع بعض
مثال تحفظه:
UserAdapter.fromApi(apiUser);
// or
StripeAdapter.pay();الجملة الذهبية: "البيانات أو الـ interface جاية بشكل مختلف، أعمل محوّل."
الصورة في دماغك: طرق مختلفة لنفس الهدف
تخيل أنت عايز تروح الشغل، ممكن:
- Car
- Train
- Bike
- Walk
كلهم هدفهم واحد، بس الطريقة مختلفة.
Goal -> choose strategy -> execute
احفظها كده: Strategy = طرق مختلفة لتنفيذ نفس الحاجة
مثال تحفظه:
paymentStrategy.pay();
shippingStrategy.calculate();
filterStrategy.filter();الجملة الذهبية: "عندي if/else كتير حسب النوع، يبقى غالبًا Strategy."
الصورة في دماغك: جرس أو Notification
تخيل قناة YouTube. القناة تنزل فيديو، كل المشتركين يوصلهم notification.
Subject changes -> notify subscribers
احفظها كده: Observer = لما يحصل حدث، بلّغ المهتمين
مثال تحفظه:
user$.subscribe(user => {});
cart$.subscribe(items => {});
form.valueChanges.subscribe(value => {});الجملة الذهبية: "لما يحصل كذا، عايز ناس تانية تعرف."
الصورة في دماغك: طبقات إضافية على الكائن
تخيل قهوة:
- قهوة عادية
- قهوة + حليب
- قهوة + حليب + كاراميل
- قهوة + حليب + كاراميل + شوكولاتة
كل واحد بيلف حول اللي قبله.
Base object -> add feature -> add feature -> final wrapped object
احفظها كده: Decorator = إضافة ميزات ديناميكية بدون تعديل الكود الأساسي
مثال تحفظه:
let coffee = new SimpleCoffee();
coffee = new MilkDecorator(coffee);
coffee = new SugarDecorator(coffee);الجملة الذهبية: "عايز أضيف ميزات اختيارية بدون أعمل subclass لكل combination."
الصورة في دماغك: شجرة فايل
تخيل folder يحتوي على files وfolders تانية. بتعاملهم بنفس الطريقة.
File: leaf node Folder: composite node Both implement same interface
احفظها كده: Composite = معاملة موحدة للفروع والأوراق
مثال تحفظه:
root.add(new File("file.txt"));
root.add(new Folder("subfolder"));
root.display(); // يعرض الكل recursivelyالجملة الذهبية: "عندي شجرة وبدي أتعامل مع كل العقد بنفس الطريقة."
الصورة في دماغك: حارس الموارد الغالية
تخيل door keeper. بدل ما تدخل مباشرة (غالي)، الحارس يتحكم.
Client -> Proxy -> Real Object (lazy load / access control)
احفظها كده: Proxy = وكيل يتحكم في الوصول للموارد
مثال تحفظه:
const image = new ImageProxy("photo.jpg"); // ما حمّش
image.display(); // الآن يحمّل لما تحتاجالجملة الذهبية: "الموارد غالية جدًا، حط وكيل يتحكم في الوصول."
الصورة في دماغك: جزّ التنفيذ عن الطلب
تخيل remote control. كل button بيمثل command. ممكن تأجل التنفيذ أو تلغيه أو تكرره.
Request -> Command Object -> Execute -> Undo
احفظها كده: Command = حوّل الطلبات لـ objects قابلة للتحكم
مثال تحفظه:
remote.pressButton(new PlayCommand(tv));
remote.undo(); // اللي بدلتشالجملة الذهبية: "عايز undo/redo أو queueing، حوّل الطلب لـ object."
الصورة في دماغك: سلوك يتغير حسب الحالة
تخيل traffic light. لما يكون RED، بتوقف. لما يكون GREEN، بتمشي.
State determines behavior
احفظها كده: State = سلوك مختلف حسب حالة الكائن
مثال تحفظه:
player.setState(new PlayingState());
player.setState(new PausedState());الجملة الذهبية: "الكائن بيتصرف مختلف حسب الحالة، فصل الحالات لـ classes."
| Pattern | احفظها بصورة | معناها في كلمة |
|---|---|---|
| Singleton | الملك الوحيد | نسخة واحدة |
| Builder | وصفة طبخ | بناء خطوة خطوة |
| Factory | مصنع | إنشاء حسب النوع |
| Facade | زرار واحد | إخفاء التعقيد |
| Adapter | مشترك كهرباء | تحويل وتوافق |
| Decorator | طبقات قهوة | إضافة ميزات ديناميكية |
| Composite | شجرة فايلات | معاملة موحدة للفروع والأوراق |
| Proxy | حارس الموارد | وكيل للوصول |
| Strategy | طرق للشغل | بدائل لنفس الهدف |
| Observer | جرس تنبيه | إشعار عند حدوث تغيير |
| Command | جهاز تحكم | طلبات كـ objects |
| State | إشارة مرور | سلوك حسب الحالة |
| لف، مثقب، وكيل، اختار، بلّغ، طلب، غيّر" |
ومعناها:
- Singleton = واحد
- Builder = ابني
- Factory = اصنع
- Facade = بسّط
- Adapter = حوّل
- Decorator = لف (طبقات)
- Composite = مثقب (tree)
- Proxy = وكيل
- Strategy = اختار
- Observer = بلّغ
- Command = طلب
- State = غيّر
أو إختصار سريع:
"واحد، ابني، اصنع، بسّط، حوّل" (الـ 5 الأساسيين)
- "لف، مثقب، وكيل" (الـ Structural الإضافيين)
- "اختار، بلّغ، طلب، غيّر" (الـ Behavioral)
- Observer = بلّغ
دي أهم mnemonic:
"واحد، ابني، اصنع، بسّط، حوّل، اختار، بلّغ"
تخيل عندك e-commerce app.
Singleton
- Logger واحد للتطبيق كله
Builder
- تبني order كبير خطوة خطوة
new OrderBuilder()
.setUser()
.addItems()
.setAddress()
.setCoupon()
.build();Factory
- تنشئ نوع user حسب role
UserFactory.create("admin");Facade
- زرار checkout يخفي كل الخطوات
checkoutFacade.buyNow(order);Adapter
- Stripe API شكلها مختلف، نعمل لها adapter
paymentAdapter.pay(order);Strategy
- الدفع له طرق مختلفة
cardPayment.pay();
paypalPayment.pay();
bankTransferPayment.pay();Observer
- لما الطلب ينجح، ابعت email وحدث UI وسجل analytics
orderCompleted$.subscribe(...);Decorator
- شحنة + تأمين + gift wrap
let order = new SimpleOrder();
order = new InsuranceDecorator(order);
order = new GiftWrapDecorator(order);Composite
- طلب يحتوي على items و sub-orders
mainOrder.add(item);
mainOrder.add(subOrder);
mainOrder.display();Proxy
- lazy load الصور الكبيرة
const image = new ImageProxy("product.jpg");Command
- كل عملية checkout بـ command قابلة للـ undo
checkout.execute(new ProcessPaymentCommand());
checkout.undo();State
- الطلب له states: pending -> processing -> shipped
order.setState(new ProcessingState());اسأل نفسك السؤال ده:
- هل عايز نسخة واحدة فقط؟ Singleton
- هل الـ object بيتبني بخطوات أو parameters كتير؟ Builder
- هل عايز تنشئ نوع مختلف حسب input؟ Factory
- هل عايز تخفي نظام معقد ورا method بسيطة؟ Facade
- هل عندك API أو مكتبة شكلها مختلف عن كودك؟ Adapter
- هل عندك طرق مختلفة لنفس العملية؟ Strategy
- هل عندك حدث وعايز تبلغ المهتمين؟ Observer
- هل عايز تضيف ميزات اختيارية بدون تعديل الكود الأساسي؟ Decorator
- هل عندك شجرة (tree) بدك معاملة موحدة للفروع والأوراق؟ Composite
- هل عندك موارد غالية وتريد lazy loading أو access control؟ Proxy
- هل عايز undo/redo أو تأجيل التنفيذ؟ Command
- هل الكائن بيتصرف مختلف حسب حالته الداخلية؟ State
احفظهم بالشكل ده:
Singleton -> الملك Builder -> الطباخ Factory -> المصنع Facade -> الريسبشن Adapter -> المحوّل Decorator -> صباغ الطبقات Composite -> بناء الشجرة Proxy -> الحارس Strategy -> الخطة Observer -> الجرس Command -> الجهاز الكهربائي State -> حالتك النفسية
دي كده شبه خريطة ذهنية. لما تشوف الكود، الصورة هتطلع في دماغك بسرعة.