أسئلة ومعلومات حول التحضير لمقابلة مطور جافا

ما هي المبادئ الصلبة؟
ما هو مبدأ المسؤولية الفردية (SRP)
يجب أن يتحمل الفصل مسؤولية واحدة فقط وسبب واحد فقط للتغيير.
وتشمل الفوائد إجراء اختبار أسهل، واقتران أقل، وتنظيم أفضل.
مثال:
public class Book {private String name;private String author;private String text;// constructor, getters, and setters}
ما هو مبدأ الفتح المغلق (OCP)؟
يجب أن تكون مكونات البرنامج (الفئات والوحدات والوظائف) مفتوحة للتوسيع ولكنها مغلقة للتعديل.
يتم تحقيق ذلك باستخدام الواجهات والفئات المجردة والميراث.
مثال:
interface Shape {double area();}class Circle implements Shape { /* implementation / } class Rectangle implements Shape { / implementation */ }
ما هو مبدأ استبدال ليسكوف (LSP)
يجب أن تكون الأنواع الفرعية قادرة على استبدال أنواعها الأساسية دون تغيير صحة البرنامج. وهذا يتبع العلاقة “is-a”.
مثال:
class Bird { /* common bird behavior / } class Sparrow extends Bird { / specific sparrow behavior */ }
ما هو مبدأ فصل الواجهة (ISP)
لا ينبغي إجبار العملاء على الاعتماد على واجهات لا يستخدمونها. تقسيم الواجهات الكبيرة إلى واجهات أصغر وأكثر تحديدًا.
مثال:
interface Worker {void work();}interface Eater {void eat();}class Robot implements Worker { /* implementation */ }
ما هو مبدأ انعكاس التبعية (DIP)
يجب ألا تعتمد الوحدات ذات المستوى الأعلى على الوحدات ذات المستوى الأدنى؛ كلا النوعين يجب أن يعتمدا على التجريدات. لا ينبغي أن تعتمد التجريدات على التفاصيل؛ التفاصيل يجب أن تعتمد على التجريدات.
// Abstractioninterface MessageSender {void sendMessage(String message);}// High-level moduleclass NotificationService {private MessageSender messageSender;public NotificationService(MessageSender messageSender) {this.messageSender = messageSender; }public void send(String message) {messageSender.sendMessage(message); }}// Low-level moduleclass EmailSender implements MessageSender {@Overridepublic void sendMessage(String message) {System.out.println("Sending Email: " + message); }}// Another Low-level moduleclass SmsSender implements MessageSender {@Overridepublic void sendMessage(String message) {System.out.println("Sending SMS: " + message); }}// Use SmsSenderMessageSender smsSender = new SmsSender();NotificationService notificationService2 = new NotificationService(smsSender);notificationService2.send("Hello via SMS!");
تعمل واجهة messageSender بمثابة التجريد. تعتمد وحدة NotificationService ذات المستوى الأعلى على هذا التجريد بدلاً من التطبيقات الملموسة.
تعتمد الوحدات النمطية ذات المستوى الأدنى مثل EmailSender وSmsSender أيضًا على التجريد من خلال تنفيذ واجهة messageSender.
ما هو التطبيع في SQL؟
ما هو التطبيع؟
يتضمن التطبيع تنظيم البيانات في قاعدة بيانات علائقية لإزالة الحالات الشاذة مثل التكرار. فهو يقسم الجداول الكبيرة والمعقدة إلى جداول أصغر مع الحفاظ على العلاقات بين البيانات.
ما أهمية التطبيع؟
تقليل التكرار: من خلال تقسيم البيانات إلى جداول أصغر، نتجنب تخزين نفس المعلومات عدة مرات.
تحسين أداء الاستعلام: تؤدي الجداول المقيسة الأصغر إلى تنفيذ أسرع للاستعلامات.
تقليل الحالات الشاذة في التحديث: يمكن إجراء التغييرات دون التأثير على السجلات الأخرى.
تحسين سلامة البيانات: يضمن بيانات متسقة ودقيقة.
سيناريوهات لتطبيق التطبيع
تكامل البيانات: يمنع حالات عدم الاتساق عند تحديث البيانات (على سبيل المثال، عندما يتغير عمر العميل).
الاستعلام الفعال: يبسط الاستعلامات المعقدة عن طريق تقسيم البيانات.
تحسين التخزين: يزيل التكرار الزائد لتوفير المساحة.
ما هو متراصة الخدمات المصغرة؟
ما هو متراصة؟
تم إنشاء التطبيق المتآلف كوحدة واحدة كاملة. فهو يربط جميع المكونات بإحكام (مثل واجهة المستخدم من جانب العميل وقاعدة البيانات والتطبيق من جانب الخادم) في قاعدة تعليمات برمجية مشتركة.
المزايا:
النشر السهل: نظرًا لأنه ملف أو دليل واحد قابل للتنفيذ، فإن النشر سهل ومباشر.
سرعة التطوير: في المراحل الأولى من عمر المشروع، يسمح المونوليث بالتطور السريع بفضل بساطته.
الأداء: يمكن لقاعدة التعليمات البرمجية المركزية التعامل مع الوظائف المختلفة بكفاءة.
ما هي الخدمات المصغرة؟
تقوم الخدمات المصغرة بتقسيم التطبيق إلى خدمات أصغر يمكن نشرها بشكل مستقل. تركز كل خدمة على مجال عمل محدد.
المزايا:
قابلية التوسع: تسمح الخدمات المصغرة بتوسيع نطاق المكونات الفردية بشكل مستقل عن بعضها البعض.
المرونة: يمكن للمطورين اختيار تقنيات مختلفة لكل خدمة.
العزل: الأخطاء في إحدى الخدمات لا تؤثر على الخدمات الأخرى.
التحديات:
التعقيد: تتطلب إدارة الخدمات المتعددة تنسيقًا موثوقًا به.
الحمل الزائد للشبكة: يؤدي الاتصال بين الخدمات إلى زمن الوصول.
تعقيد النشر: قد يكون تنسيق التحديثات عبر خدمات متعددة أمرًا صعبًا.
ما هو تعدد الأشكال؟
تجاوز الطريقة:
عندما توفر فئة فرعية تطبيقًا محددًا لطريقة محددة بالفعل في فئتها الفائقة.
طريقة التحميل الزائد:
عندما يكون لدى الفصل طرق متعددة بنفس الاسم، ولكن مع معلمات مختلفة (عدد أو أنواع مختلفة من الوسائط).
ما هو الغرض من بناة القطاع الخاص؟
يتم استخدام المنشئين الخاصين في فئات المرافق أو الفئات الثابتة.
تحتوي هذه الفئات على أساليب ثابتة أو أعضاء فقط.
تجنب الميراث (تجنب الفئات الفرعية)
وفد المقاولين:
يسمح المنشئون الخاصون بتفويض المنشئ، حيث يستدعي المنشئون المحددون المنشئ الخاص المشترك.
نمط سينجلتون
بالنسبة لـ JVM
تجميع:
عندما تقوم بتجميع ملف .java، يقوم برنامج التحويل البرمجي Java بإنشاء ملفات .class التي تحتوي على كود بايت (تمثيل متوسط).
Bytecode مستقل عن النظام الأساسي ويمكن تشغيله على أي نظام باستخدام JVM متوافق.
النظام الفرعي لمحمل الفئة:
المسؤول عن تحميل الطبقات في الذاكرة.
فهو يقرأ ملفات .class، وينشئ بيانات ثنائية ويخزنها في منطقة الطريقة.
إنشاء كائن فئة يمثل الفئة المحملة في ذاكرة الكومة.
Example: Student s1 = new Student(); Class c1 = s1.getClass();
الروابط:
يتكون من ثلاث خطوات:
التحقق: التحقق من صحة ملف .class.
التحضير: للذاكرة الجانبية لمتغيرات الفئة وتهيئتها.
الحل (اختياري): يحل المراجع الرمزية للفئات أو الأساليب الأخرى.
التهيئة:
ينفذ أدوات التهيئة الثابتة (مثل الكتل الثابتة) ويقوم بتهيئة المتغيرات الثابتة.
تتم تهيئة متغيرات المثيل عند إنشاء الكائن.
محرك التنفيذ:
تحويل bytecode إلى رمز الجهاز.
يتضمن تجميع Just-In-Time (JIT) لتحسين الأداء.
باختصار، يسمح JVM لبرامج Java بالعمل في أي مكان عن طريق تفسير الكود الثانوي وإدارة الذاكرة.
ما هي الطريقة التجريدية الخاصة؟
حالات الاستخدام للطرق الخاصة في الفئات المجردة:
على الرغم من أن الأساليب المجردة لا يمكن أن تكون خاصة، إلا أنه يمكنك استخدام الأساليب الخاصة في فئة مجردة لأغراض مختلفة:
الأساليب المساعدة: تنفيذ الوظائف المشتركة التي تتم مشاركتها بواسطة طرق أخرى.
التغليف: إخفاء تفاصيل التنفيذ من الفئات الفرعية.
الفئات الشبيهة بالبنية: قم بإنشاء فئات صغيرة باستخدام أساليب خاصة تعمل كحاويات للبيانات
ما هو جامع القمامة؟
ذاكرة الكومة:
يتم إنشاء كائنات Java في ذاكرة الكومة، وهي منطقة ذاكرة مخصصة خصيصًا.
تصبح بعض الكائنات غير متاحة (لم يعد البرنامج يشير إليها).
جامع القمامة (GC):
يقوم GC بتحديد وحذف الكائنات غير المستخدمة لتحرير الذاكرة.
يعمل تلقائيا في الخلفية.
نوعان:
Minor GC: يزيل الكائنات غير المتوفرة في جيل الشباب.
Major GC (Full GC): مسح الكائنات في الجيل القديم.
فوائد:
لا يحتاج المطورون إلى حذف الكائنات يدويًا.
يضمن GC توفر الذاكرة ويمنع OutOfMemoryErrors.
ما هو OOP؟
المبادئ الأربعة لـ OOP:
التغليف: تجميع البيانات (السمات) والأساليب (الوظائف) معًا في فئة لإخفاء تفاصيل التنفيذ وتوفير واجهة نظيفة.
الوراثة: إنشاء فئات جديدة بناءً على الفئات الموجودة، ووراثة سماتها وسلوكها. وهذا يشجع على إعادة استخدام التعليمات البرمجية.
تعدد الأشكال: يسمح بمعاملة الكائنات من فئات مختلفة بنفس الطريقة من خلال واجهة مشتركة. وهذا يعطي المرونة ويجعل النظام أسهل في التوسع (قابلية التوسع).
التجريد: التركيز على الميزات المهمة مع إخفاء التعقيدات غير الضرورية. يعمل التجريد على تبسيط التصميم ويجعل من السهل صيانته وإدارته.
تلعب خصائص ACID دورًا رئيسيًا في ضمان موثوقية واتساق المعاملات.
الذرية:
يتم تنفيذ المعاملات بالكامل أو لا يتم تنفيذها على الإطلاق.
لا يوجد التزام جزئي: إذا فشلت المعاملة في المنتصف، فسيتم التراجع عن جميع التغييرات التي تم إجراؤها على قاعدة البيانات.
مثال: ضع في اعتبارك تحويل 100 دولار من الحساب X إلى الحساب Y. إذا فشلت المعاملة بعد سحب المبلغ من X ولكن قبل إضافته إلى Y، تظل قاعدة البيانات متسقة.
تناسق:
يجب أن تحافظ قاعدة البيانات على قيود التكامل الخاصة بها قبل وبعد المعاملة.
مثال: إذا كان الإجمالي قبل المعاملة هو 700 دولار أمريكي (X: 500 دولار أمريكي، Y: 200 دولار أمريكي)، فيجب أن يظل كما هو بعد المعاملة (X: 400 دولار أمريكي، Y: 300 دولار أمريكي).
عزل:
يمكن تشغيل معاملات متعددة بشكل متزامن دون التأثير على بعضها البعض.
التغييرات التي تم إجراؤها بواسطة معاملة واحدة لن تكون مرئية للآخرين حتى يتم الالتزام بها.
يتم ضمان نتيجة تعادل ذلك كما لو تم تنفيذ المعاملات بشكل متسلسل.
مثال: يمنع عزل المعاملات الحالات غير المتناسقة الناتجة عن العمليات المتشابكة.
متانة:
بمجرد تنفيذ المعاملة، تصبح تغييراتها دائمة.
تنجو التغييرات من فشل النظام أو تعطله.
تخزين البيانات على المدى الطويل مضمون.
مثال: حتى بعد إعادة تشغيل النظام، تظل التغييرات التي تم الالتزام بها محفوظة.
تذكر أن خصائص ACID توفر الأساس لعمليات قاعدة بيانات موثوقة ومتسقة!
ما هو قالب الإستراتيجية؟
الوصف: تعريف عائلة من الخوارزميات، وتغليف كل منها، وجعلها قابلة للتبديل. يسمح هذا للخوارزمية بالتغيير بشكل مستقل عن العملاء الذين يستخدمونها.
مثال:
// Interface for eat behaviorinterface EatBehavior {void eat();}// Concrete implementations of eat behaviorclass NormalDiet implements EatBehavior {@Overridepublic void eat() {// Normal food }}class LosingWeightDiet implements EatBehavior {@Overridepublic void eat() {// Healthy food }}// Cat class with eat behaviorabstract class Cat {EatBehavior eatBehavior;public void eat() { eatBehavior.eat(); }public void setEatBehavior(EatBehavior eatBehavior) { this.eatBehavior = eatBehavior; }}// UsageCat cat = new Cat();cat.setEatBehavior(new LosingWeightDiet());cat.eat(); // Cat eats with a healthier diet
الأنماط الإبداعية
تركز هذه القوالب على إنشاء مثيل للفصول الدراسية.
تشمل الأمثلة
طريقة المصنع,
بيان المشكلة: لنفترض أننا نريد إنشاء أنواع مختلفة من المنتجات (مثل السيارات والدراجات والدراجات) دون ربط الكود الخاص بنا بإحكام بتطبيقات محددة.
المكونات الرئيسية:
المنتج: فئة مجردة أو واجهة تحدد العمليات العامة للكائنات التي سيقوم المصنع بإنشائها.
المنتجات الملموسة: الفئات الحقيقية التي تنفذ واجهة المنتج وتمثل أنواع الكائنات الملموسة.
Creator: فئة أو واجهة مجردة تعلن عن طريقة المصنع. وهو مسؤول عن إنشاء كائنات المنتج، ولكنه يفوض الإنشاء الفعلي للفئات الفرعية.
المبدعون الملموسون: فئات فرعية من المبدعين الذين يقومون بتنفيذ طريقة المصنع. إنهم يقررون أي منتج محدد سيتم إنشاؤه بناءً على معلمات الإدخال أو التكوين.
طريقة المصنع: طريقة محددة في فئة المنشئ تقوم بإنشاء كائنات المنتج. عادةً ما يتم الإعلان عنه بشكل تجريدي في Creator ويتم تنفيذه في Concrete Creators.
مثال في Java: لنفترض أن لدينا مصنعًا ينتج أنواعًا مختلفة من المركبات. هنا مثال مبسط:
// Abstract Productinterface Product {void display();}// Concrete Productsclass Car implements Product {public void display() {System.out.println("Car created"); }}class Bike implements Product {public void display() {System.out.println("Bike created"); }}// Creator (Factory)interface Factory {Product factoryMethod();}// Concrete Creatorsclass ConcreteFactoryA implements Factory {public Product factoryMethod() {return new Car(); }}class ConcreteFactoryB implements Factory {public Product factoryMethod() {return new Bike(); }}public class FactoryMethodExample {public static void main(String[] args) {Factory factoryA = new ConcreteFactoryA();Product productA = factoryA.factoryMethod();productA.display();Factory factoryB = new ConcreteFactoryB(); Product productB = factoryB.factoryMethod(); productB.display();}
منشئ
نمط البناء هو نمط تصميم إبداعي يسمح لك ببناء كائنات معقدة خطوة بخطوة،
وذلك بفصل بنائها عن تمثيلها. فيما يلي مثال بسيط في Java:
// Define the class you want to buildclass Post {private final String title;private final String text;private final String category;Post(Builder builder) { this.title = builder.title; this.text = builder.text; this.category = builder.category;}// Getters for propertiespublic String getTitle() { return title;}public String getText() { return text;}public String getCategory() { return category;}// Builder classpublic static class Builder { private String title; private String text; private String category; public Builder title(String title) { this.title = title; return this; } public Builder text(String text) { this.text = text; return this; } public Builder category(String category) { this.category = category; return this; } public Post build() { return new Post(this); }}// Usagepublic class Main {public static void main(String[] args) {Post post = new Post.Builder().title("Java Builder Pattern").text("Explaining how to implement the Builder Pattern in Java").category("Design Patterns").build();System.out.println("Title: " + post.getTitle()); System.out.println("Text: " + post.getText()); System.out.println("Category: " + post.getCategory()); }}
النموذج الأولي
النموذج الأولي
نموذج النموذج الأولي هو نمط تصميم إبداعي يسمح لك بإنشاء كائنات جديدة عن طريق نسخ كائن موجود.
بدلاً من إنشاء مثيلات جديدة من الصفر، يمكنك استنساخ نموذج أولي موجود، والذي يمكن أن يكون أكثر كفاءة ومرونة. دعونا نلقي نظرة على مثال في جافا:
تحديد واجهة النموذج الأولي: أولاً نقوم بإنشاء فئة أو واجهة مجردة تسمى Tree، بالطريقة المجردة copy():
public abstract class Tree {public abstract Tree copy();}
نماذج ملموسة: بعد ذلك، نقوم بتنفيذ فئتين ملموستين ممتدتين Tree: PlasticTree و PineTree. تمثل هذه الفئات أنواعًا محددة من الأشجار وتوفر طريقة التنفيذ الخاصة بها copy():
public class PlasticTree extends Tree {@Overridepublic Tree copy() {PlasticTree plasticTreeClone = new PlasticTree(this.getMass(), this.getHeight());plasticTreeClone.setPosition(this.getPosition());return plasticTreeClone; }}public class PineTree extends Tree {@Overridepublic Tree copy() {PineTree pineTreeClone = new PineTree(this.getMass(), this.getHeight());pineTreeClone.setPosition(this.getPosition());return pineTreeClone; }}
في هذه الفئات نقوم بتخصيص عملية الاستنساخ وفقًا لنوع الشجرة المحدد. على سبيل المثال، نقوم بنسخ كتلة, ارتفاع و موضع من الشجرة الأصلية.
الاستخدام: الآن دعونا ننشئ نماذجنا الأولية الملموسة:
جافا
public class Main {public static void main(String[] args) {Tree originalPlasticTree = new PlasticTree(10, 5);Tree clonedPlasticTree = originalPlasticTree.copy(); Tree originalPineTree = new PineTree(15, 8); Tree clonedPineTree = originalPineTree.copy(); // Use the cloned trees as needed // ... }}
ما هي الأنماط الهيكلية؟
تشير هذه القوالب إلى بنية الفصل وتكوينه.
نمط المحول
نمط المحول هو نمط تصميم هيكلي يسمح لواجهتين غير متوافقتين بالعمل معًا.
وهو بمثابة جسر بين هذه الواجهات، مما يسمح لهم بالتعاون دون تغيير كود المصدر الخاص بهم.
محول الكائن:
في هذا الأسلوب، نستخدم التركيب لتفويض المنطق إلى المحول.
يحتوي المحول على Adaptee ويقوم بتفويض طريقة request() إلى طريقة المحددRequest() في Adaptee.
class Adaptee {void specificRequest() {System.out.println("Adaptee's specific request"); }}// Target interfaceinterface Target {void request();}// Adapter (using composition)class Adapter implements Target {private final Adaptee adaptee;Adapter(Adaptee adaptee) { this.adaptee = adaptee;}@Overridepublic void request() { adaptee.specificRequest(); }}
محول الفئة:
يتطلب وراثة متعددة (مستحيل مباشرة في جافا).
يمكننا تحقيق ذلك باستخدام واجهات ذات طرق افتراضية.
يرث المحول من فئتي Target وAdaptee.
// Target interfaceinterface Target {void request();}// Adaptee (existing class)class Adaptee {void specificRequest() {System.out.println("Adaptee's specific request"); }}// Adapter (using class inheritance)class Adapter extends Adaptee implements Target {@Overridepublic void request() {specificRequest(); }}
الفوائد والمقايضات:
يعمل محول الفئة بشكل جيد لتعيين الأساليب واحد لواحد.
يوفر Object Adaptor مزيدًا من المرونة ويتجنب تعديل التعليمات البرمجية المصدر.
نمط الديكور
نمط الديكور هو نمط تصميم إبداعي يسمح لك بإضافة وظائف وسلوك ديناميكيًا إلى كائن بدونه
للتأثير على سلوك الكائنات الأخرى الموجودة في نفس الفئة. إنه مفيد بشكل خاص عندما تريد توسيع قدرات كائن ما،
دون تغيير بنيته.
ملخص:
يوفر نمط الديكور واجهة موسعة للكائن الأصلي عن طريق “تغليفه” بوظائف إضافية.
نحن نفضل التكوين على الميراث لتقليل الحمل على الفئات الفرعية.
يمكن إضافة أدوات الديكور في وقت التشغيل، مما يوفر المرونة.
مثال على السيناريو: لنفترض أن لدينا كائن ChristmasTree ونريد تزيينه بعناصر مختلفة مثل الإكليل والزينة وأضواء الفقاعات. سوف نتبع اتفاقيات التصميم الأصلية لعصابة الأربعة.
تطبيق:
First, create a ChristmasTree interface:Javapublic interface ChristmasTree {String decorate();}Implement the interface with a basic tree:Javapublic class ChristmasTreeImpl implements ChristmasTree {@Overridepublic String decorate() {return "Christmas tree"; }}Next, create an abstract TreeDecorator class that implements ChristmasTree and holds the decorated tree:Javapublic abstract class TreeDecorator implements ChristmasTree {private final ChristmasTree tree;public TreeDecorator(ChristmasTree tree) { this.tree = tree;}@Overridepublic String decorate() { return tree.decorate(); }}Now create specific decorators. For example, BubbleLights:Javapublic class BubbleLights extends TreeDecorator {public BubbleLights(ChristmasTree tree) { super(tree); }@Overridepublic String decorate() { return super.decorate() + " with Bubble Lights"; }}public class Garland extends TreeDecorator {public Garland(ChristmasTree tree) {super(tree);}@Overridepublic String decorate() { return super.decorate() + " with Garland";}}Usage:Create decorated trees:public class DecoratorPatternDemo {public static void main(String[] args) {ChristmasTree tree1 = new Garland(new ChristmasTreeImpl());System.out.println(tree1.decorate()); // Output: "Christmas tree with Garland"ChristmasTree tree2 = new BubbleLights(new Garland(new Garland(new ChristmasTreeImpl()))); System.out.println(tree2.decorate()); // Output: "Christmas tree with Garland with Garland // with Bubble Lights" }}
يسمح النمط بإضافة عناصر ديكور في وقت التشغيل، مما يوفر مرونة في التزيين حسب الحاجة.
تذكر أن نمط الديكور يُستخدم على نطاق واسع في المواقف التي تريد فيها توسيع سلوك كائن ما دون تعديل بنيته الأساسية.
نمط الواجهة
نمط الواجهة هو نمط تصميم هيكلي يعمل على تبسيط التفاعل مع نظام فرعي معقد من خلال توفير واجهة موحدة.
إنه بمثابة “الباب الأمامي” لإخفاء التعقيد الداخلي وتسهيل استخدام النظام للعملاء.
مركب
النمط المركب هو نمط تصميم هيكلي يسمح لك بتركيب الكائنات في هياكل شجرة لتمثيل التسلسلات الهرمية الجزئية.
الفكرة الرئيسية وراء النموذج المركب هي بناء هيكل شجرة من الكائنات، حيث تشترك الكائنات الفردية (الورقية) والكائنات المركبة في واجهة مشتركة.
المكون الأساسي (القسم): سنحدد واجهة القسم البسيطة كمكون أساسي لدينا:
public interface Department {void printDepartmentName();}Leaf Components (FinancialDepartment and SalesDepartment): Let’s create classes for financial and sales departments, both implementing the Department interface:public class FinancialDepartment implements Department { // Implementation details (e.g., id, name) public void printDepartmentName() { System.out.println(getClass().getSimpleName()); }}public class SalesDepartment implements Department { // Implementation details (e.g., id, name) public void printDepartmentName() { System.out.println(getClass().getSimpleName()); }}These leaf classes implement the printDepartmentName() method and don’t contain references to other Department objects.Composite Element (HeadDepartment): As a composite class, let’s create a HeadDepartment that holds a collection of Department components:import java.util.ArrayList;import java.util.List;public class HeadDepartment implements Department { private Integer id; private String name; private List childDepartments; public HeadDepartment(Integer id, String name) { this.id = id; this.name = name; this.childDepartments = new ArrayList<>(); } public void printDepartmentName() { childDepartments.forEach(Department::printDepartmentName); } public void addDepartment(Department department) { childDepartments.add(department); } public void removeDepartment(Department department) { childDepartments.remove(department); }}
تطبق فئة HeadDepartment طريقة printDepartmentName () وتوفر طرقًا لإضافة الأقسام الفرعية وإزالتها.
الاستخدام: يمكنك إنشاء مثيلات للأقسام الفرعية (مثل القسم المالي وقسم المبيعات) والأقسام المركبة (مثل القسم الرئيسي). إضافة الأقسام الورقية إلى المركب وطباعة أسمائها.
public class Main {public static void main(String[] args) { Department finance = new FinancialDepartment(); Department sales = new SalesDepartment(); HeadDepartment headDepartment = new HeadDepartment(1, "Company Departments"); headDepartment.addDepartment(finance); headDepartment.addDepartment(sales); headDepartment.printDepartmentName(); }}Output:FinancialDepartmentSalesDepartment
يتيح لك النمط المركب إنشاء هياكل شجرة مرنة حيث
يمكن معالجة الأشياء والتركيبات الفردية (المركبات) بشكل موحد.
ما هي وظيفة التجزئة !!!
دالة التجزئة هي دالة رياضية تأخذ مدخلاً (أو “رسالة”) وترجع سلسلة ثابتة الطول من الأحرف،
والذي عادة ما يكون عبارة عن سلسلة من الأرقام والحروف. يسمى هذا الإخراج “قيمة التجزئة” أو ببساطة “التجزئة”.
تُستخدم وظائف التجزئة على نطاق واسع في علوم الكمبيوتر والتشفير ولها عدة خصائص مهمة:
كيف يتم استخدام دالة التجزئة وكيف تعمل؟
الحتمية: سيؤدي نفس الإدخال دائمًا إلى إنشاء نفس التجزئة.
سريع: يمكن للوظيفة حساب قيمة التجزئة لأي إدخال بسرعة.
فريد (تقريبًا): يجب أن يولد مدخلان مختلفان قيم تجزئة مختلفة (نحاول تقليل “التصادمات”).
لا رجعة فيه (أحادي الاتجاه): نظرًا للتجزئة، يجب أن يكون من غير الممكن حسابيًا استعادة المدخلات الأصلية.
موحدة: يتم توزيع قيم التجزئة بشكل موحد في مساحة المصدر.
تُستخدم دالات التجزئة على نطاق واسع في العديد من التطبيقات، مثل:
سلامة البيانات: التأكد من عدم تغيير البيانات أو التلاعب بها من خلال مقارنة قيم التجزئة.
تخزين كلمة المرور: للتخزين الآمن لكلمات المرور المجزأة بدلاً من كلمات المرور الحقيقية.
التشفير: يستخدم في التوقيعات الرقمية وخوارزميات التشفير الأخرى.
جداول التجزئة: لاسترجاع البيانات بكفاءة في البرمجة.
أعطني مثالاً على خريطة التجزئة – كيف يمكنك تنفيذها؟
SHA (خوارزمية التجزئة الآمنة):
ويتضمن متغيرات مثل SHA-1 وSHA-256 وSHA-384 وSHA-512.
يتم استخدام SHA-256 وSHA-512 على نطاق واسع في تقنيات التشفير و blockchain (مثل Bitcoin).
import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;public class HashExample {public static void main(String[] args) {try {// The input string to be hashedString input = "Hello, world!"; // Create a MessageDigest instance for SHA-256 MessageDigest digest = MessageDigest.getInstance("SHA-256"); // Compute the hash byte[] hash = digest.digest(input.getBytes()); // Convert the hash bytes to a hexadecimal string StringBuilder hexString = new StringBuilder(); for (byte b : hash) { String hex = String.format("%02x", b); hexString.append(hex); } // Print the resulting hash System.out.println("SHA-256 Hash: " + hexString.toString()); } catch (NoSuchAlgorithmException e) { System.err.println("Error: " + e.getMessage()); } }}
بيانات الإدخال: يحتوي متغير الإدخال على البيانات التي نريد تجزئتها.
تهيئMessageDigest: يتم إنشاء مثيل لـMessageDigest باستخدام getInstance(“SHA-256”)، الذي يحدد خوارزمية SHA-256.
التجزئة: تحسب طريقة الملخص قيمة التجزئة للبيانات المدخلة.
التحويل السداسي العشري: نظرًا لأن قيمة التجزئة بتنسيق ثنائي، فإننا نستخدم حلقة لتحويلها إلى سلسلة سداسية عشرية أكثر قابلية للقراءة.
وضع والتصحيح؟ متى يجب أن نستخدمها؟
PUT وPATCH هما طريقتان HTTP تستخدمان لتحديث الموارد على الخادم، لكنهما يختلفان في كيفية تطبيق التغييرات:
يضع:
التحديث الكامل:
يتم استخدام PUT لاستبدال مورد موجود بالكامل.
يجب تقديم المورد بالكامل في الطلب، حتى لو تم تغيير جزء منه فقط.
إذا لم يكن المورد موجودًا، فغالبًا ما يقوم PUT بإنشائه (على الرغم من أن هذا السلوك قد يختلف).
عاجز:
تؤدي طلبات PUT المتكررة التي تحتوي على نفس البيانات دائمًا إلى نفس حالة المورد.
مثال: تحديث ملف تعريف المستخدم:
jsonPUT /users/123{"name": "Velislav","email": "velislav@example.com","age": 30}
إذا تغير الاسم فقط، ولكن ظل البريد الإلكتروني والعمر كما هو، فيجب أن يظلا موجودين في الطلب.
بقع:
التحديث الجزئي:
يتم استخدام التصحيح لتحديث مورد موجود جزئيًا.
يتم إرسال الحقول التي تم تغييرها فقط في الطلب.
عاجز (في الغالب):
مثل PUT، عادةً ما تؤدي طلبات PATCH المتكررة التي تحتوي على نفس البيانات إلى نفس حالة المورد.
ومع ذلك، قد يعتمد السلوك على تطبيق الخادم.
مثال: تحديث اسم المستخدم فقط:
jsonPATCH /users/123{"name": "Velislav"}
هنا، يتم تحديث حقل الاسم فقط، وتظل الحقول الأخرى دون تغيير.
الفرق الرئيسي:
يستبدل PUT المورد بأكمله، بينما يغير PATCH فقط الحقول المحددة للمورد.
طرق HTTP مع وصف موجز.
GET: يستخدم لاسترداد البيانات من الخادم دون تعديلها. غالبا ما تستخدم لجلب الموارد أو المعلومات.
POST: يُستخدم لإرسال البيانات إلى الخادم، عادةً لإنشاء مورد جديد. على سبيل المثال، عند إرسال نموذج أو تحميل ملف.
PUT: يُستخدم لتحديث مورد موجود على الخادم أو استبداله بالكامل. في حالة عدم وجود المورد، يمكن إنشاؤه.
التصحيح: يستخدم للتحديث الجزئي لمورد موجود، مع تعديل الحقول المحددة فقط.
DELETE: يستخدم لحذف مورد من الخادم.
HEAD: يشبه GET، ويستخدم لاسترداد الرؤوس فقط دون نص المورد.
الخيارات: يعرض طرق HTTP المسموح بها.
TRACE: يستخدم بشكل أساسي لأغراض التشخيص عن طريق تكرار الطلب مرة أخرى إلى العميل
CONNECT: ينشئ نفقًا للخادم، وغالبًا ما يستخدم لاتصالات SSL/TLS.
واجهة وظيفية
الواجهة الوظيفية في Java هي واجهة تحتوي على طريقة مجردة واحدة فقط. تُستخدم هذه الواجهات بشكل أساسي مع تعبيرات لامدا ومراجع الأساليب، مما يسمح بأسلوب برمجة وظيفي أقصر وأكثر قابلية للقراءة.
الميزات الرئيسية:
- طريقة مجردة واحدة: الواجهة الوظيفية لها طريقة مجردة واحدة فقط. وهذا هو جوهر وظيفتها.
- الأساليب الافتراضية والثابتة: يمكن أن تحتوي الواجهات الوظيفية على أساليب افتراضية وثابتة، لكنها لا تعتبر الطريقة المجردة الوحيدة.
- @FunctionalInterface الشرح: على الرغم من أن هذا التعليق التوضيحي اختياري، إلا أنه يساعد في الإشارة إلى أن الواجهة المحددة تهدف إلى أن تكون وظيفية. إذا تمت إضافة أساليب مجردة إضافية إلى الواجهة، فسيقوم المترجم بإلقاء خطأ.
مثال:
@FunctionalInterfaceinterface Calculator { int calculate(int a, int b);}// Using lambda expressionpublic class Main { public static void main(String[] args) { // Implementing the calculate method using a lambda Calculator addition = (a, b) -> a + b; Calculator multiplication = (a, b) -> a * b; System.out.println("Addition: " + addition.calculate(5, 3)); // Output: 8 System.out.println("Multiplication: " + multiplication.calculate(5, 3)); // Output: 15 }}
حالة الاستخدام:
الواجهة Calculator في المثال هناك طريقة مجردة واحدة فقط calculateمما يجعلها واجهة وظيفية.
يتيح لنا ذلك استخدام تعبيرات لامدا لتنفيذ أقصر وأكثر أناقة.
الواجهات الوظيفية الشائعة الاستخدام في Java:
توفر Java العديد من الواجهات الوظيفية المضمنة في الحزمة java.util.function، مثل:
- المسند: يقبل المدخلات ويعيد قيمة منطقية.
- وظيفة: يأخذ مدخلاً ويعيد نتيجة من النوع R.
- مزود: يوفر قيمة بدون إدخال.
- مستهلك: يأخذ قيمة وينفذ إجراءً.
تجعل الواجهات الوظيفية العمل أسهل، خاصة في سيناريوهات مثل العمل مع المجموعات أو التدفقات أو المهام غير المتزامنة.
إنها تسمح لـ Java بتبني نماذج البرمجة الوظيفية مع الاحتفاظ بطابعها الموجه للكائنات.
ما هي وظيفة النظام الأعلى؟
الدالة ذات الترتيب الأعلى هي دالة تقبل وظائف أخرى كوسائط أو ترجع دالة كنتيجة لها. وبعبارة أخرى، فهي تعمل بوظائف، وتعاملهم على أنهم “مواطنون من الدرجة الأولى”. هذه ميزة قوية في نماذج البرمجة الوظيفية التي تتيح التجريد وإعادة استخدام التعليمات البرمجية والتكوين.
مثال على وظيفة ذات ترتيب أعلى في Java:
import java.util.function.Function;public class Main { public static void main(String[] args) { // Higher-order function: applies a function to a value Function<Integer, Integer> squareFunction = x -> x * x; int result = applyFunction(5, squareFunction); System.out.println("Square of 5: " + result); // Output: 25 } public static int applyFunction(int value, Function<Integer, Integer> function) { return function.apply(value); }}
في المثال أعلاه:
- الطريقة
applyFunctionهي وظيفة ذات ترتيب أعلى لأنها تقبل وظيفة أخرى (Function<Integer, Integer>) كمعلمة.
سمات:
- يقبل الوظائف كوسائط: يمكن للوظائف ذات الترتيب الأعلى أن تأخذ وظائف أخرى كمدخلات لتنفيذ عمليات محددة.
- وظائف الإرجاع: يمكنهم إنشاء وظائف جديدة وإرجاعها ديناميكيًا.
- يشجع على إعادة استخدام التعليمات البرمجية: يعزز التعليمات البرمجية المعيارية والقابلة لإعادة الاستخدام، حيث يمكن تمرير الوظائف ودمجها مع بعضها البعض.
حالة الاستخدام:
في Java، غالبًا ما تُستخدم الدوال ذات الترتيب الأعلى في البرمجة الوظيفية مع التدفقات، و lambdas، ومراجع الأساليب. على سبيل المثال:
List<String> names = Arrays.asList("John", "Jane", "Jake");names.stream() .filter(name -> name.startsWith("J")) // Takes a lambda function as argument .forEach(System.out::println); // Takes a method reference as argument
تضيف الوظائف ذات الترتيب العالي المرونة والقوة إلى برامج Java، مما يسمح للمطورين بكتابة تعليمات برمجية واضحة وموجزة ومعبرة!
بعض الأمثلة الحقيقية مع إجابات من المقابلات
- يفهم الأساسيات مثل تعدد الأشكال والأساليب الثابتة وتجمع السلسلة
- – على دراية بالمجموعات (مثل HashSet وTreeSet) وحالات استخدامها.
- تحديد نطاقات الفول بشكل صحيح (مفردة، نموذج أولي)
- يفهم ما هو حقن التبعية والغرض منه.
- يعرف كيفية تنفيذ علاقات متعدد إلى متعدد باستخدام جداول الوصلات.
- يفهم الغرض من الفهارس (ولو بشكل سطحي)
- يمكن التمييز بين بنيات متجانسة وهندسة الخدمات الصغيرة
- فهم المفاضلات الأساسية (قابلية التوسع وقابلية الصيانة)
- لا يفهم بشكل صحيح مبدأ استبدال ليسكوف وانعكاس التبعية
- من الصعب إعطاء أمثلة ملموسة للمبدأ المفتوح/المغلق.
- لا توجد معرفة عميقة بإدارة دورة حياة الفول.
- إنه لا يفهم حقن التبعية المتقدم.
- لديه فهم سطحي للفهارس (الفهارس المركبة، تحسين الاستعلام).
- لست على دراية بمستويات العزلة والقفل المتفائل/المتشائم.
الايجابيات:
- عملت مع التعليمات البرمجية القديمة في نظام كبير ومعقد.
- إنه على دراية بـ SOLID.
- لديه معرفة بالتيارات.
- شرح الفهارس وACID.
- مستوى جيد في اللغة الإنجليزية
السلبيات: - لا توجد مسؤولية عن النشر أو البنية التحتية أو المشاركة في التصميم المعماري.
- لديه بعض المعرفة بمبادئ OOP، لكنه يواجه صعوبة كبيرة في شرحها ويخلط بين بعض المفاهيم.
- معرفة عامة بالمجموعات، ولكن بها ثغرات وغير مؤكدة تمامًا.
- لا يفهم الفرق بين التزامن والتوازي، وليس لديه معرفة قوية بشكل خاص بالتزامن.
- ولم تنظر إلى بنية الخدمات الصغيرة بالتفصيل.
- الغموض في بعض مفاهيم قواعد البيانات (النقاش حول الفهارس كان سطحيا).
- لا يمكن شرح Livelock.
- هناك فجوات في فهم الكتلة النهائية.
- معرفة محدودة بتفاصيل معالجة الاستثناءات.
- الخلط بين معدّلات الوصول (المحمية مقابل الحزمة الخاصة)
الرأي العام هو ذلك
غير مناسب لمنصب مطور Mid-Java بسبب الثغرات الموجودة في معرفته التقنية. - وأوضح الصلبة بشكل جيد.
- شرح OOP جيدا.
- شرح التكوين (لكنه كان صعبًا بعض الشيء في البداية).
- فهم ممتاز للمجموعات.
- اشرح الفرق بين القوائم والمجموعات.
- ناقش HashSet.
- مناقشة HashMap.
- مناقشة ConcurrentHashMap.
- فهم جيد لهياكل البيانات – الأكوام وطوابير الانتظار والأشجار.
- معرفة جيدة بهندسة JVM.
- تم شرح التزامن مقابل التوازي جيدًا، وأظهر معرفة جيدة بالتطبيقات متعددة الخيوط.
- فهم جيد لـ REST.
- شرح فهارس قاعدة البيانات بشكل جيد.
- شرح الأنواع المختلفة من الصلات.

ترك الرد