English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

مثال على نموذج بناء (Builder) في تصميم Android: شرح تفصيلي

این مقاله مثال‌های Android Programming Design Pattern Builder را توضیح می‌دهد. برای شما به اشتراک گذاشته شده است، به شرح زیر:

یکمین

مدل Builder یک مدل ایجادکننده است که به تدریج یک شیء پیچیده ایجاد می‌کند، به کاربر اجازه می‌دهد تا در حالی که جزئیات اجرایی را نمی‌داند، بتواند فرآیند ساخت شیء را به طور دقیق‌تری کنترل کند. این مدل برای جدا کردن فرآیند ساخت شیء و قطعات آن است تا فرآیند ساخت و نمایش قطعات جدا شوند.

به دلیل اینکه یک شیء پیچیده دارای بخش‌های زیادی است، به عنوان مثال، اتومبیل دارای چرخ‌ها، فرمان، موتور و قطعات مختلف است، چگونه می‌توان این قطعات را به یک اتومبیل تبدیل کرد، این فرآیند طولانی و پیچیده است، برای این نوع از موارد، برای اینکه در فرآیند ساخت به خارج از جزئیات اجرایی پنهان شوند، می‌توان از مدل Builder استفاده کرد تا قطعات و فرآیند مونتاژ جدا شوند، به این ترتیب فرآیند ساخت و قطعات می‌توانند به صورت مستقل توسعه یابند و پیچیدگی بین آنها به حداقل می‌رسد.

تعریف

جمع‌آوری یک فرآیند پیچیده‌ای از یک شیء با نمایش آن جدا می‌کند، بنابراین فرآیند جمع‌آوری مشابه می‌تواند نمایش‌های مختلفی ایجاد کند.

سهام استفاده

(1) زمانی که روش‌های مشابه، ترتیب اجرای مختلفی دارند و منجر به نتایج مختلف می‌شوند.

(2) چندین قطعه یا جزء می‌توانند به یک شیء متصل شوند، اما نتایج اجرایی مختلف دارند.

(3) کلاس محصول بسیار پیچیده است یا ترتیب فراخوانی‌های کلاس محصول مختلف است که منجر به اثرات مختلف می‌شود، در این صورت استفاده از مدل Builder بسیار مناسب است.

(4) زمانی که یک شیء به طور خاص پیچیده است، مانند تعداد زیادی پارامتر، و بسیاری از پارامترها دارای ارزش پیش‌فرض هستند.

چارچوب UML模式 Builder چهارم

مقدار معرفی:

Product کلاس محصول - کلاس انتزاعی محصول;

Builder - کلاس Builder انتزاعی، ساختار محصول را استاندارد می‌کند، معمولاً توسط فرزندان آن فرآیند ساخت خاص را انجام می‌دهد;

ConcreateBuilder - کلاس Builder خاص;

Director - فرآیند مونتاژ یکپارچه;

حقیقتاً پیاده‌سازی ساده Builder

عملیات مونتاژ کامپیوتر پیچیده است و ترتیب مونتاژ ثابت نیست، برای اینکه بهتر بفهمیم، ما فرآیند مونتاژ کامپیوتر را به سه بخش ایجاد سیستم‌سرور، تنظیم سیستم‌عامل، تنظیم مانیتور ساده‌سازی کرده‌ایم، سپس از Director و Builder خاص برای ساخت شیء کامپیوتر استفاده می‌کنیم.

مثال على الكود:

/**
 * صنف抽象ی برای کامپیوتر، یعنی نقش Product
 */
public abstract class Computer {
  protected String mBoard;
  protected String mDisplay;
  protected String mOS;
  protected Computer(){}
  /**
   * تعيين لوحة الأم
   * @param board
   */
  public void setBoard(String board){
    this.mBoard = board;
  }
  /**
   * تعيين عرض
   * @param display
   */
  public void setDisplay(String display){
    this.mDisplay = display;
  }
  /**
   * تعيين نظام التشغيل
   */
  public abstract void setOS();
  @Override
  public String toString(){
    return "Computer [mBoard=" + mBoard + ", mDisplay=" + mDisplay + ", mOS=" + mOS + "]";
  }
}
/**
 * فئة Computer محددة، Macbook
 */
public class Macbook extends Computer {
  protected Macbook(){}
  @Override
  public void setOS() {
    mOS = "Mac OS X 10";
  }
}
/**
 * فئة Builder تعريفية
 */
public abstract class Builder {
  /**
   * تعيين وحدة المعالجة المركزية
   * @param board
   */
  public abstract void buildBoard(String board);
  /**
   * تعيين عرض
   * @param display
   */
  public abstract void buildDisplay(String display);
  /**
   * تعيين نظام التشغيل
   */
  public abstract void buildOS();
  /**
   * إنشاء Computer
   * @return
   */
  public abstract Computer create();
}
/**
 * ميزان التفاصيل، MacbookBuilder
 */
public class MacbookBuilder extends Builder {
  private Computer mComputer = new Macbook();
  @Override
  public void buildBoard(String board) {
    mComputer.setBoard(board);
  }
  @Override
  public void buildDisplay(String display) {
    mComputer.setDisplay(display);
  }
  @Override
  public void buildOS() {
    mComputer.setOS();
  }
  @Override
  public Computer create() {
    return mComputer;
  }
}
/**
 * كلاس Director، مسؤول عن بناء Computer
 */
public class Director {
  Builder mBuilder = null;
  public Director(Builder builder){
    mBuilder = builder;
  }
  /**
   * بناء الكائن
   * @param board اللوحة
   * @param display العرض
   */
  public void construct(String board, String display){
    mBuilder.buildBoard(board);
    mBuilder.buildDisplay(display);
    mBuilder.buildOS();
  }
}
/**
 * كود الاختبار
 */
public class Test {
  public static void main(String[] args){
    // بناء
    Builder builder = new MacbookBuilder();
    // Director
    Director pcDirector = new Director(builder);
    // غلفة عملية البناء
    pcDirector.construct("لوحة رئيسية من Intel","عرض Retina");
    // بناء الحاسوب، إخراج معلوماته
    System.out.println("معلومات الحاسوب: " + builder.create().toString());
  }
}

نتيجة الإخراج:

معلومات الحاسوب: الحاسوب [مزود بلوحة رئيسية من Intel، عرض Retina، نظام التشغيل Mac OS X 10]

في المثال السابق، يتم بناء كائن Macbook من خلال MacbookBuilder المحدد، بينما يغلف Director عملية بناء كائنات المنتجات المعقدة، ويخفي تفاصيل البناء. يجمع Builder و Director بين بناء كائن معقد وإدراكه، مما يسمح لنفس عملية البناء أن تخلق كائنات مختلفة.

من المهم ملاحظة أن في عملية التطوير الفعلية، دور Director غالباً ما يتم تجاوزه. ويتم استخدام Builder مباشرة لجمع الأجسام، وعادة ما يكون هذا Builder هو الندرة التتابعية، نقطة أساسية هي أن كل طريقة setter تعود إلى نفسها، أي return this، مما يسمح للطريقة setter بالندرة التتابعية، الكود تقريباً كالتالي:}}

new TestBuilder()
  .setA("A")
  .create();

بهذه الطريقة، ليس فقط أن تم إزالة دور Director، ولكن الهيكل بأكمله أصبح أكثر بساطة، كما يمكن التحكم بشكل دقيق في عملية تجميع Product.

النوع الاشكالي من نموذج Builder - الندرة التتابعية

مثال على الكود:

public class User {
  private final String name;     //مجبوري
  private final String cardID;    //مجبوري
  private final int age;       //اختياري
  private final String address;   //اختياري
  private final String phone;    //اختياري
  private User(UserBuilder userBuilder){
    this.name=userBuilder.name;
    this.cardID=userBuilder.cardID;
    this.age=userBuilder.age;
    this.address=userBuilder.address;
    this.phone=userBuilder.phone;
  }
  public String getName() {
    return name;
  }
  public String getCardID() {
    return cardID;
  }
  public int getAge() {
    return age;
  }
  public String getAddress() {
    return address;
  }
  public String getPhone() {
    return phone;
  }
  public static class UserBuilder{
    private final String name;
    private final String cardID;
    private int age;
    private String address;
    private String phone;
    public UserBuilder(String name,String cardID){
      this.name=name;
      this.cardID=cardID;
    }
    public UserBuilder age(int age){
      this.age=age;
      return this;
    }
    public UserBuilder address(String address){
      this.address=address;
      return this;
    }
    public UserBuilder phone(String phone){
      this.phone=phone;
      return this;
    }
    public User build(){
      return new User(this);
    }
  }
}

النقاط التي يجب الانتباه إليها:

طريقة التركيب الخاصة بفئة User خاصة، لا يمكن للدعاء أن ينشئ كائن User مباشرة.

جميع خصائص فئة User غير القابلة للتغيير. جميع الخصائص أضيفت إليها修饰ة final، ويتم تعيين القيم في طريقة التركيب. وتقدم فقط طرق الحصول على القيم.

يستقبل بناء الفئة الداخلية فقط المعامل الإلزامية، ويستخدم المعامل الإلزامي修饰ة final.

طريقة النداء:

new User.UserBuilder("Jack","10086")
    .age(25)
    .address("GuangZhou")
    .phone("13800138000")
    .build();

على عكس الطرق السابقة من خلال كلا من مكونات التركيب والsetter/getter، تكون القابلة للقراءة أقوى. يمكن أن يكون هناك مشكلة واحدة محتملة هي إنتاج كائنات إضافية من البناء، مما يؤدي إلى استهلاك ذاكرة. ومع ذلك، في معظم الحالات، يتم استخدام修饰ة الثابتة (static) في فئة البناء الداخلية، لذا فإن هذه المشكلة ليست كبيرة جدًا.

عن الأمان للتعامل مع الخيوط

نموذج البناء ليس آمنًا للتعامل مع الخيوط، إذا كنت تريد التحقق من صحة معامل في داخـل فئة البناء، يجب القيام بذلك بعد إنشاء الجسم

مثال صحيح:

public User build() {
 User user = new user(this);
 if (user.getAge() > 120) {
  throw new IllegalStateException("عمر خارج النطاق"); // آمن للتعامل مع الخيوط
 }
 return user;
}

مثال خطأ:

public User build() {
 if (age > 120) {
  throw new IllegalStateException("Age out of range"); // غير آمن بالتوازي
 }
 return new User(this);
}

السابع- مثال على استخدام نموذج Builder

1- AlertDialog.Builder في Android

private void showDialog(){
    AlertDialog.Builder builder=new AlertDialog.Builder(context);
    builder.setIcon(R.drawable.icon);
    builder.setTitle("Title");
    builder.setMessage("Message");
    builder.setPositiveButton("Button1", new DialogInterface.OnClickListener() {
      @Override
      public void onClick(DialogInterface dialog, int which) {
        //TODO
      }
    });
    builder.setNegativeButton("Button2", new DialogInterface.OnClickListener() {
      @Override
      public void onClick(DialogInterface dialog, int which) {
        //TODO
      }
    });
    builder.create().show();
}

2- إنشاء كائن OkHttpClient في OkHttp

OkHttpClient okHttpClient = new OkHttpClient.Builder()
         .cache(getCache())
         .addInterceptor(new HttpCacheInterceptor())
         .addInterceptor(new LogInterceptor())
         .addNetworkInterceptor(new HttpRequestInterceptor())
         .build();

3- إنشاء كائن Retrofit في Retrofit

رetrofit retrofit = new Retrofit.Builder()
     .client(createOkHttp())
    .addConverterFactory(GsonConverterFactory.create())
     .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
     .baseUrl(BASE_URL)
     .build();

في الواقع، يتم تجاهل دور Director في الاستخدام اليومي، وعندما يتم ذكر نموذج البuilder في كود المصادر للعديد من الإطارات، يتم اختيار النموذج البسيط أكثر من نموذج GOF الكلاسيكي.

ثمانية، النقاط الإيجابية والسلبي

النقاط الإيجابية:

الغلاف الجيد، الذي يجعل العملاء لا يحتاجون إلى معرفة التفاصيل الداخلية لتطوير المنتج

البuilder مستقل، ويمكنه التوسع بشكل كبير

النقاط السلبية:

يتم إنشاء الكثير من كائنات البuilder وكائنات الدايركتور، مما يؤدي إلى استهلاك ذاكرة

يمكن للقراء المهتمين بمعرفة المزيد عن الأندرويد مراجعة مواضيع هذا الموقع: 'دليل البدء في تطوير الأندرويد والتحسين'، 'قائمة بأساليب الت调试 والتغلب على المشاكل الشائعة للأندرويد'، 'تحليل استخدام العناصر الأساسية للأندرويد'، 'تحليل تقنيات العرض للأندرويد'، 'تحليل تقنيات التخطيط للأندرويد'، و 'تحليل استخدام العناصر المختلفة للأندرويد'.

نتمنى أن يساعدك ما ذكرته في هذا المقال في تصميم برامج الأندرويد.

بيان: محتويات هذا المقال تم جمعها من الإنترنت، وتنتمي إلى حقوق الملكية للمراجع، وقد تم إدراجها من قبل المستخدمين عبر الإنترنت، ولم يتحمل هذا الموقع حقوق الملكية، ولا تم تعديل المحتويات بشكل إنساني، ولا يتحمل أي مسؤولية قانونية ذات صلة. إذا اكتشفت أي محتوى يشتبه في حقوق النسخ، فأنت موصى به أن ترسل بريدًا إلكترونيًا إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال '#' بـ '@') لإبلاغنا، وتقديم الأدلة ذات الصلة، وسوف يتم حذف المحتوى المشبوه بشكل فوري إذا تم التحقق من صحة الشكوى.

سيكون ممتعًا لك