java شرح - متى ستستخدم نموذج باني؟




8 Answers

الفرق الرئيسي بين باني ومصنع IMHO ، هو أن بناء أمر مفيد عندما تحتاج إلى القيام بالكثير من الأشياء لبناء كائن. على سبيل المثال تخيل DOM. يجب عليك إنشاء الكثير من العقد والسمات للحصول على الكائن النهائي. يتم استخدام المصنع عندما يتمكن المصنع بسهولة من إنشاء الكائن بأكمله داخل استدعاء طريقة واحدة.

أحد الأمثلة على استخدام أداة البناء هو إنشاء مستند XML ، لقد استخدمت هذا النموذج عند إنشاء أجزاء HTML على سبيل المثال قد يكون لدي منشئ لإنشاء نوع معين من الجدول وقد يكون لديه الطرق التالية (لا يتم عرض المعلمات) :

BuildOrderHeaderRow()
BuildLineItemSubHeaderRow()
BuildOrderRow()
BuildLineItemSubRow()

سيقوم هذا المنشئ بعد ذلك بصرف HTML بالنسبة لي. هذا أسهل بكثير للقراءة ثم المشي من خلال طريقة إجرائية كبيرة.

تحقق من نمط البناء على ويكيبيديا .

prototype design

ما هي بعض الأمثلة الشائعة في العالم الحقيقي لاستخدام نمط البناء؟ ماذا يشتري لك؟ لماذا لا تستخدم فقط نمط مصنع؟




النظر في مطعم. إنشاء "وجبة اليوم" هو نمط مصنع ، لأنك تخبر المطبخ "أحضر لي وجبة اليوم" ويقرر المطبخ (المصنع) أي كائن يولد ، بناء على معايير خفية.

يظهر المنشئ إذا طلبت بيتزا مخصصة. في هذه الحالة ، يخبر النادل الشيف (باني) "أحتاج إلى بيتزا ، أضيفي الجبن والبصل ولحم الخنزير المقدد إلى ذلك!" وبالتالي ، يقوم المنشئ بتعريف السمات التي يجب أن يحتويها الكائن الذي تم إنشاؤه ، ولكنه يخفي كيفية تعيينها.




بالنسبة لمشكلة متعددة الخيوط ، كنا بحاجة إلى كائن معقد يتم إنشاؤه لكل سلسلة محادثات. يمثل الكائن البيانات التي تتم معالجتها ، ويمكن أن يتغير اعتمادًا على إدخال المستخدم.

هل يمكننا استخدام مصنع بدلا من ذلك؟ نعم فعلا

لماذا لم نفعل؟ منشئ يبدو أكثر منطقية.

يتم استخدام المصانع لإنشاء أنواع مختلفة من الكائنات التي هي من النوع الأساسي نفسه (تنفيذ نفس الواجهة أو الطبقة الأساسية).

بناة بناء نفس النوع من الكائن مرارا وتكرارا ، ولكن البناء هو ديناميكي لذلك يمكن تغييره في وقت التشغيل.




أثناء استعراض إطار Microsoft MVC ، حصلت على فكرة حول نمط البناء. جئت عبر نمط في فئة ControllerBuilder. هذه الفئة هي لإعادة فئة المصنع تحكم ، والتي تستخدم بعد ذلك لبناء وحدة تحكم الخرسانة.

ميزة أرى في استخدام نمط باني هو أنه يمكنك إنشاء مصنع خاص بك وتوصيله في إطار العمل.

@ تيثا ، يمكن أن يكون هناك مطعم (الإطار) يديره الرجل الإيطالي ، الذي يخدم بيتزا. من أجل تحضير البيتزا الإيطالية (Object Builder) يستخدم أوين (Factory) مع قاعدة بيتزا (فئة أساسية).

الآن الرجل الهندي يتولى المطعم من الرجل الإيطالي. خوادم المطعم الهندسي (الإطار) دوسا بدلاً من البيتزا. من أجل إعداد رجل دوسا الهندي (كائن البناء) يستخدم مقلاة (مصنع) مع مايدا (الطبقة الأساسية)

إذا نظرت إلى السيناريو ، فإن الطعام مختلف ، والطريقة التي يتم إعداد الطعام بها مختلفة ، ولكن في نفس المطعم (في نفس الإطار). ينبغي بناء المطعم بطريقة يمكن أن تدعم الصينية أو المكسيكية أو أي مطبخ. منشئ الكائن داخل الإطار يسهل القيام بتوصيل نوع المطبخ الذي تريده. فمثلا

class RestaurantObjectBuilder
{
   IFactory _factory = new DefaultFoodFactory();

   //This can be used when you want to plugin the 
   public void SetFoodFactory(IFactory customFactory)
   {
        _factory = customFactory;
   }

   public IFactory GetFoodFactory()
   {
      return _factory;
   }
}






لطالما كرهتُ نمط البانيء كشيء غير عملي ، متسلل ، وكثيرًا ما أساء استخدامه من قبل المبرمجين الأقل خبرة. إنه نمط منطقي فقط إذا احتجت إلى تجميع الكائن من بعض البيانات التي تتطلب خطوة ما بعد التهيئة (أي بمجرد جمع كل البيانات - قم بعمل شيء ما). بدلا من ذلك ، في 99 ٪ من الوقت يتم استخدام بناة ببساطة لتهيئة أعضاء الفئة.

في مثل هذه الحالات ، يكون من الأفضل أن تقوم ببساطة بتعريف withXyz(...) نوعًا من withXyz(...) داخل الصف وأن تجعلهم withXyz(...) مرجعًا لنفسه.

النظر في هذا:

public class Complex {

    private String first;
    private String second;
    private String third;

    public String getFirst(){
       return first; 
    }

    public void setFirst(String first){
       this.first=first; 
    }

    ... 

    public Complex withFirst(String first){
       this.first=first;
       return this; 
    }

    public Complex withSecond(String second){
       this.second=second;
       return this; 
    }

    public Complex withThird(String third){
       this.third=third;
       return this; 
    }

}


Complex complex = new Complex()
     .withFirst("first value")
     .withSecond("second value")
     .withThird("third value");

لدينا الآن فئة واحدة أنيقة تدير عملية التهيئة الخاصة بها وتقوم بنفس الوظيفة التي تقوم بها الشركة ، إلا أنها أكثر أناقة.




عندما كنت أرغب في استخدام XMLGregorianCalendar القياسي الخاص بي XML إلى تنظيم marshaling من DateTime في Java ، سمعت الكثير من التعليقات حول الوزن الثقيل والمرهل لاستخدامه. كنت أحاول أن comtrol حقول XML في XS: هياكل التاريخ والوقت لإدارة المنطقة الزمنية ، ميلي ثانية ، الخ

لذلك صممت أداة مساعدة لإنشاء تقويم XMLGregorian من GregorianCalendar أو java.util.Date.

بسبب مكان عملي ، لا يُسمح لي بمشاركته عبر الإنترنت بدون قانوني ، ولكن إليك مثالاً لكيفية استخدام العميل له. يقوم بتجريد التفاصيل والفلاتر بعض تنفيذ XMLGregorianCalendar التي هي أقل استخدامًا لـ xs: datetime.

XMLGregorianCalendarBuilder builder = XMLGregorianCalendarBuilder.newInstance(jdkDate);
XMLGregorianCalendar xmlCalendar = builder.excludeMillis().excludeOffset().build();

منح هذا النمط أكثر من عامل تصفية كما أنه يعيّن الحقول في xmlCalendar كـ undefined بحيث يتم استبعادها ، فإنه لا يزال "يبني" عليه. لقد أضفت بسهولة خيارات أخرى إلى أداة الإنشاء لإنشاء xs: date و xs: time struct وأيضًا للتلاعب في إزاحة المنطقة الزمنية عند الحاجة.

إذا كنت قد رأيت رمزًا يقوم بإنشاء XMLGregorianCalendar واستخدامه ، فسترى كيف أن هذا جعل التلاعب أسهل كثيرًا.




مثال عظيم في العالم الحقيقي هو استخدام وحدة اختبار الفصول الدراسية. يمكنك استخدام sut (النظام تحت اختبار) بناة.

مثال:

صف دراسي:

public class CustomAuthenticationService
{
    private ICloudService _cloudService;
    private IDatabaseService _databaseService;

    public CustomAuthenticationService(ICloudService cloudService, IDatabaseService databaseService)
    {
        _cloudService = cloudService;
        _databaseService = databaseService;
    }

    public bool IsAuthorized(User user)
    {            
        //Implementation Details
        return true;

}

اختبار:

    [Test]
    public void Given_a_User_With_Permission_When_Verifying_If_Authorized_Then_Authorize_It_Returning_True()
    {
        CustomAuthenticationService sut = new CustomAuthenticationServiceBuilder();
        User userWithAuthorization = null;

        var result = sut.IsAuthorized(userWithAuthorization);

        Assert.That(result, Is.True);
    }

sut Builder:

public class CustomAuthenticationServiceBuilder
{
    private ICloudService _cloudService;
    private IDatabaseService _databaseService;

    public CustomAuthenticationServiceBuilder()
    {
        _cloudService = new AwsService();
        _databaseService = new SqlServerService();
    }

    public CustomAuthenticationServiceBuilder WithAzureService(AzureService azureService)
    {
        _cloudService = azureService;

        return this;
    }

    public CustomAuthenticationServiceBuilder WithOracleService(OracleService oracleService)
    {
        _databaseService = oracleService;

        return this;
    }

    public CustomAuthenticationService Build()
    {
        return new CustomAuthenticationService(_cloudService, _databaseService);
    }

    public static implicit operator CustomAuthenticationService (CustomAuthenticationServiceBuilder builder)
    {
        return builder.Build();
    }
}



Related

java design-patterns builder