> ## Content Index
> Fetch the complete content index at: https://informatic-ar.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# قل لا ل Constructor بمعاملات كثيرة
- URL: https://informatic-ar.com/builder_pattern/
- Published: 2012-10-15T21:57:34.000Z
- Updated: 2026-10-03T22:32:31.000Z
- Author: وجدي عصام
- Tags: جافا, java, builder pattern, constructor, java beans, overloading, pattern, private constructor, دوال البناء, #wordpress-archive, #Import 2026-10-03 20:48

**ما هو عدد دوال البناء اذا أردت عمل overloading لأكثر من 4 معاملات بترتيب مختلف؟**

هذه المرة الثانية نشن هجوماً على دالة البناء constructor، في مقالنا الأول ([هل مللت من دالة البناء](https://informatic-ar.com/constructor-vs-factory/) ) فضلنا دالة static factory method على ال constructor بسبب مقروئيتها وامكانية دعمها للCaching لو أردت في وقت لاحق.

عندما تريد انشاء كائن من كلاس به متغيرات ضرورية وقت الانشاء وبها اختياريه فسوف نقول أيضاً: **لا لل constructors ولا أيضاً لل static factory methods**.

**للتوضيح**: كما نعلم أنه لا يمكن انشاء كائن بدون استدعاء دالة البناء بشكل او أخر، فعندما نقول لا لدالة البناء فنحن نقصد لا بجعلها متاحة للكلاينت public constructor ولكن نريد اخفائها private constructor عن الكلاينت، في مقالة هل مللت من دالة البناء قمنا بجعل دالة البناء private وقمنا باستدعائها من دالة public static في نفس الكلاس، بينما هنا في موضوعنا هذه المقالة سوف نخفى دالة البناء private constructor ونقوم بانشاء الكائن من خلال inner class في نفس الكلاس، لماذا؟ اكمل القرائة الآن.

هذه المقالة جزء من سلسلة كيف تحترف لغة الجافا وهي موجهة لأي مطور OOP ويستخدم لغة الجافا

- [الإسلوب الصحيح لكتابه Utility Classes](https://informatic-ar.com/utility%5Fclasses/)
- [هل مللت من دالة البناء Constructor ؟](https://informatic-ar.com/constructor-vs-factory/)
- استخدام ال Builder Pattern في دالة البناء (المقال الحالي)
- [لا تستخدم Public الا وقت الحاجة](https://informatic-ar.com/inaccessible%5Fclass/)
- [كيف تصمم الPackages جيداً في تطبيقات جافا](https://informatic-ar.com/packages%5Fin%5Fjava/)
- [جافا دائماً Passing by Value](https://informatic-ar.com/java%5Fpassing%5Fby%5Fvalue/)
- [نظرة حول الدالة Equals](https://informatic-ar.com/java-object-equals/)
- [خارطة طريق لتعلم الجافا](https://informatic-ar.com/how%5Fto%5Flearn%5Fjava/)

## **Telescoping Constructor**

دوال البناء العادية constructor ودوال الstatic factory قد لا يستطيعوا تقديم الحل الأفضل في حالة كان لديك العديد من المعاملات المرسلة لدالة البناء وخصوصاً لو كانت هناك معاملات اختيارية ،، على سبيل المثال لو أردنا عمل كلاس يمثل بيتزا يقوم العميل بتخصيص طلبها على حسب ما يريد ، ففي البدايه عليه باختيار الحجم ثم يحدد ما يريده من الخيارات المتاحة هي جبنة وهوت دوق وببروني ،،

بطريقة دوال البناء العادية سوف يخرج لدينا كلاس بهذا الشكل:

```java
// Pizza construction

public class Telescoping
{
    public static void main(String[] args)
    {
        PizzaTelescoping pizza = new PizzaTelescoping(3, false, false, true);
    }
}

class PizzaTelescoping
{
    // required
    private int size;

    // optional
    private boolean cheese;
    private boolean hotdog;
    private boolean peppernoi;

    public PizzaTelescoping(int size)
    {
        this(size, false);
    }

    public PizzaTelescoping(int size, boolean cheese)
    {
        this(size, cheese, false);
    }

    public PizzaTelescoping(int size, boolean cheese, boolean hotdog)
    {
        this(size, cheese, hotdog, false);
    }

    public PizzaTelescoping(int size, boolean cheese, boolean hotdog, boolean peppernoi)
    {
        this.size = size;
        this.cheese = cheese;
        this.hotdog = hotdog;
        this.peppernoi = peppernoi;
    }
}
```

الحل أعلاه (وهو يسمى Telescoping Constructor) قد يكون مقبول الأن ، لكن ماذا لو كانت عدد الخيارات هي 20 مثلاً؟ هل ستقوم بكتابة الكم الهائل من دوال البناء هذه .. ناهيك عن صعوبة قرائه الكود الذي ينشئ الكلاس.. ناهيك عن الأخطاء الناتجة من تمرير هذا الكم الهائل من المعاملات للدالة، فقد يخطئ ممرر القيم ويمرر true للهوت دوق وfalse للجنبه بينما المستخدم يريد العكس (بكل تأكيد المترجم سعيد ولن يصدر رسالة خطأ لهذا الخطأ)، وكل ذلك بسبب صعوبة تذكر هذا الكم من المعاملات.. بنفس الأمر ال static factory لن ينفع في هذه الحالة لأنك ستحتاج لعمل overloads لهذا العدد من الدوال..

## **جافا بينز Java Beans**

الحل الثاني الممكن هو استخدام اسلوب جافا بينز Java Beans وذلك عن طريق انشاء الكائن فارغ أولاً، ثم وضع القيم التي يريدها المبرمج، المثال التالي يوضح ذلك:

```java
// Pizza Construction using Java Beans Style

public class PizzaJavaBeans
{
    public static void main(String[] args)
    {
        PizzaBeans pizza = new PizzaBeans();
        pizza.setSize(10);
        pizza.setCheese(true);
    }
}

class PizzaBeans
{
    // required
    private int size;

    // optional
    private boolean cheese;
    private boolean hotdog;
    private boolean peppernoi;

    public PizzaBeans()
    {
    }

    public void setSize(int size)
    {
        this.size = size;
    }

    public void setCheese(boolean cheese)
    {
        this.cheese = cheese;
    }
    public void sethotdog(boolean hotdog)
    {
        this.hotdog = hotdog;
    }
    public void setPeppernoi(boolean pep)
    {
        this.peppernoi = pep;
    }
}
```

هذا الحل تلافي مشكلة دوال البناء Telescoping Constructor ، فهو سهل القرائة وواضح جداً.. لكن هناك مشكلتين متعلقات بJava Beans Pattern أولها أن الكائن بعد انشائه سوف يكون في حالة غير مستقره حيث أنه لا يستطيع وقت انشاء الكائن التحقق من القيم المدخلة فيه، وبالتالي من الممكن ان ينشىء الكائن وبعد ذلك تمرر له قيم خاطئة ويكون في حالة غير سليمة inconsistent state. المشكلة الثانية هي أن الكلاس بعد استخدام هذا الأسلوب لا يمكن أن يكون كلاس Immutable ويتطلب جهداً من المبرمج للتأكد من أن الكلاس مؤمن من مشاكل الThreads (بمعنى Thread-Safety).

## Builder Pattern

الحل الصحيح هو بجمع الأمان والتحقق الذي تحققه دوال البناء و مقروئية الJava Beans Pattern وذلك باستخدام الBuilder Pattern. وفكرتها هي بدلاً من انشاء الكائن مباشرة، سوف تقوم باستدعاء دالة بناء (أو دالة static factory -تذكرها أولاً قبل دالة البناء!-) بالقيم الأساسية المطلوبة وستحصل على كائن Builder وبعد ذلك سوف تستدعي دوال داخل هذا الكائن يمكنك أن تقول بأنها setter method للقيم الاختياريه وأخيراً تقوم باستدعاء الدالة build الموجودة داخل الbuilder لكي ترجع لك الكائن (والذي يكون Immutable) . المثال:

```java
// Pizza Construction using Builder Pattern

public class PizzaBuilderPattern
{
    public static void main(String[] args)
    {
        Pizza pizza = new Pizza.Builder(10).cheese(true).peppernoi(true).build();
    }
}

class Pizza
{
    // required
    private int size;

    // optionals
    private boolean cheese;
    private boolean hotdog;
    private boolean peppernoi;

    public static class Builder
    {
        private int size;

        private boolean cheese;
        private boolean hotdog;
        private boolean peppernoi;

        public Builder(int size)
        {
            this.size = size;
        }

        public Builder cheese(boolean cheese)
        {
            this.cheese = cheese;
            return this;
        }
        public Builder hotdog(boolean hotdog)
        {
            this.hotdog = hotdog;
            return this;
        }
        public Builder peppernoi(boolean pep)
        {
            this.peppernoi = pep;
            return this;
        }

        public Pizza build()
        {
            return new Pizza(this);
        }
    }

    private Pizza(Builder builder)
    {
        this.size = builder.size;
        this.cheese = builder.cheese;
        this.hotdog = builder.hotdog;
        this.peppernoi = builder.peppernoi;
    }
}
```

انظر لكيفية تكوين الكائن:

```java
Pizza pizza = new Pizza.Builder(10).cheese(true).peppernoi(true).build();
```

وهكذا حققنا المقروئية والسهوله ويتم تحقيق الأمان والتحقق عن طريق فحص المتغيرات في دالة البناء Pizza ومن ثم عمل throw لException اذا وجد هناك خطأ وفي داخل داله الbuild يتم عمل catch اذا وجد هذا الexception.

مثال أخر لتوضيح الفرق لبناء كائن بطريقة telescoping و builder pattern من كلاس يحتوي على ثلاث متغيرات :

```java
// if no parameters are required and all are optional
Box box0 = new Box.Builder().build();
Box box1 = new Box.Builder().length(1).build();
Box box2 = new Box.Builder().length(1).width(2).build();
Box box3 = new Box.Builder().length(1).width(2).height(3).build();

// if length is required and others are optional - that's your Box
Box box1 = new Box.Builder(1).build();
Box box2 = new Box.Builder(1).width(2).build();
Box box3 = new Box.Builder(1).width(2).height(3).build();

// For comparison - your constructors. It's less obvious what is length,
// width or height
Box box1 = new Box(1);
Box box2 = new Box(1, 2);
Box box3 = new Box(1, 2, 3);
```

من أحدى المأخذ وهي الأداء حيث لبناء الكائن سوف نحتاج لبناء كائن من نوع Builder أولاً وان كان ذلك طفيفاً، لذلك لا ينظر اليه الا في حالات قليله.

في العالم الحقيقي أستخدم الBuilder Patterns كثيراً جداً فهو اسهل واكثر مقروئية وأفضل للكلاينت، [والآن نسخه Netbeans 7.2 أصبحت تضع خيار Replace Constructor with Builder من ضمن قائمة ال Refactoring](http://wiki.netbeans.org/NetBeans%5F72%5FNewAndNoteworthy?ref=informatic-ar.com#Replace%5FConstructor%5FWith%5FBuilder)، ولو ألقيت نظرة على مكتبات الجافا الحديثة مثلاً Guava ستجد الكثير جداً من ال Builder Pattern والتي تفضل على دوال البناء العادية..

لذلك اذا كان لديك مثل هذه الكومة وحتى ان لم يكن لديك overloading :

```java
public class Car
{
    private String manufacturer;
    private String model;
    private int horsePower;
    private int numOfSeats;
    private Color color;
    private String cylinder;
    private double length;
    private double width;
    private double price;

    public Car(String manufacturer, String model, int horsePower, int numOfSeats, Color color,
               String cylinder, double length, double width, double price)
    {
        this.manufacturer = manufacturer;
        this.model = model;
        this.horsePower = horsePower;
        this.numOfSeats = numOfSeats;
        this.color = color;
        this.cylinder = cylinder;
        this.length = length;
        this.width = width;
        this.price = price;
    }
}
```

فقم بتحويلها الى Builder Pattern واستمتع بال New Look والمزايا الجديدة لكلاسك.

## خلاصة

يفضل استخدام الBuilder Pattern عن تصميمك لكلاس يحتوي على دالة بناء أو static factory تستقبل أكثر من 4 متغيرات وما فوق وخصوصاً لو كانت هذه المتغيرات اختياريه، سوف تكسب المقروئية من الكود أكثر من Telescoping Constructor وأكثر أماناً من استخدام Java Beans Pattern.