android源码中的设计模式(1)--builder模式

转载请注明出处:http://blog.csdn.net/tyhj_sf/article/details/51724383

引言

本文为分析Android API源码用到的设计模式系列文章之一,专门分析Builder Pattern(建造者模式),如果想了解其他若干种设计模式,可阅读作者的系列文章。
下图列表为23种经典设计模式分类,本系列文章将结合Android源码详细分析。
这里写图片描述

概念

按照Gof的说法:Builder Pattern是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。 [构建与表示分离,同构建不同表示]

与抽象工厂的区别:在建造者模式里,有个指导者,由指导者来管理建造者,用户是与指导者联系的,指导者联系建造者最后得到产品。即建造模式可以强制实行一种分步骤进行的建造过程。

  Builder模式是将复杂的内部创建封装在内部,对于外部调用的人来说,只需要传入Builder和Builder方法,对于内部是如何建造成成品的,调用者无需关心。

  举个简单的例子,如汽车,有很多部件,车轮,方向盘,发动机还有各种小零件等等,部件很多,但远不止这些,如何将这些部件装配成一部汽车,这个装配过程也很复杂(需要很好的组装技术), Builder模式就是为了将部件和组装分开。

结构图

这里写图片描述

  1. builder:给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。

  2. ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。

  3. Director:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。

  4. Product:要创建的复杂对象。

一般用法

我们根据建造者模式的结构图写一个简单的实例。
类及接口定义:

 public interface Builder { 
    void buildPartA(); 
    void buildPartB(); 
    void buildPartC(); 
  
    Product getResult(); 
  } 

   //具体建造工具
  public class ConcreteBuilder implements Builder { 
    Part partA, partB, partC; 

    public void buildPartA() {
      //这里是具体如何构建partA的代码
    }; 
    public void buildPartB() { 
      //这里是具体如何构建partB的代码
    }; 
     public void buildPartC() { 
      //这里是具体如何构建partB的代码
    }; 
     public Product getResult() { 
      //返回最后组装成品结果
    }; 
  }

   //建造者
  public class Director {
    private Builder builder; 
  
    public Director( Builder builder ) { 
      this.builder = builder; 
    } 
    public void construct() { 
      builder.buildPartA();
      builder.buildPartB();
      builder.buildPartC(); 
    } 
  } 


  public interface Product { }
  public interface Part { }

调用过程:

ConcreteBuilder builder = new ConcreteBuilder();
  Director director = new Director( builder ); 
  
  director.construct(); 
  Product product = builder.getResult();

特别推荐书《Effective Java》中介绍的Builder Pattern用法:

// Builder Pattern

  public class NutritionFacts {

  private final int servingSize;
  private final int servings;
  private final int calories;
  private final int fat;
  private final int sodium;
  private final int carbohydrate;
  
  public static class Builder {
  // Required parameters
  private final int servingSize;
  private final int servings;
  // Optional parameters - initialized to default values
  private int calories = 0;
  private int fat = 0;
  private int carbohydrate = 0;
  private int sodium = 0;
  
  public Builder(int servingSize, int servings) {
      this.servingSize = servingSize;
      this.servings = servings;
  }

  public Builder calories(int val){
       calories = val; 
       return this; 
   }

  public Builder fat(int val){ 
      fat = val;
      return this; 
   }

  public Builder carbohydrate(int val){ 
      carbohydrate = val; 
      return this; 
  }

  public Builder sodium(int val){ 
      sodium = val; 
      return this; 
  }

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

  private NutritionFacts(Builder builder) {
  servingSize = builder.servingSize;
  servings = builder.servings;
  calories = builder.calories;
  fat = builder.fat;
  sodium = builder.sodium;
  carbohydrate = builder.carbohydrate;
  }
}

对象的构造过程:

NutritionFactscocaCola = new NutritionFacts.Builder(240, 8).

  calories(100).sodium(35).carbohydrate(27).build();

Android源码中的builder模式

在Android开发中,AlertDialog的创建过程中就用到了Builder模式。官方文档中给出的创建AlertDialog对象的示例代码如下:

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Add the buttons
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // User clicked OK button
           }
       });
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // User cancelled the dialog
           }
       });
// Set other dialog properties
...

// Create the AlertDialog
AlertDialog dialog = builder.create();

下面我们来看看类AlertDialog和类Builder源码。
1. 我们先看看类AlertDialog定义的成员变量及构造方法,代码如下:

public class AlertDialog extends Dialog implements DialogInterface {
    private AlertController mAlert;

    protected AlertDialog(Context context) {
        this(context, resolveDialogTheme(context, 0), true);
    }

    protected AlertDialog(Context context, int theme) {
        this(context, theme, true);
    }

    AlertDialog(Context context, int theme, boolean createThemeContextWrapper) {
        //省略
       ··········
    }

    protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
       //省略
       ··········
    }
    //后面跟省略
    ·············
    ·············
 }

类AlertDialog的所有组件如title、icon、button、message等都封装在AlertController类中,方便对包含的组件统一设置。类AlertController的源码结构如下图:
这里写图片描述
这里写图片描述

Builder类的源码结构如下:
这里写图片描述

AlertController类相当重要,AlertDialog类的大部分getter和setter方法的实现都依赖于这个类的getter和setter方法,见下面的代码例子。

AlertDialog类2个典型getter和setter方法:

 public ListView getListView() {
        return mAlert.getListView();
    }

    @Override
    public void setTitle(CharSequence title) {
        super.setTitle(title);
        mAlert.setTitle(title);
    }

其中变量mAlert是AlertController类的实例。

另外,
再看看Builder类2个典型setter方法:

 public Builder setMessage(CharSequence message) {
            P.mMessage = message;
            return this;
        }

        public Builder setIcon(int iconId) {
            P.mIconId = iconId;
            return this;
        }

其中变量P是AlertController类的内部类AlertParams的实例。由类:AlertDialog、AlertController、AlertParams三者的关系可知,对类AlertController、AlertParams的设置表现为对AlertDialog的组件的设置。
而且,上面这段代码中方法的返回值均为this,这使得build过程可以连续进行,像这样:

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
AlertDialog dialog =
builder.setTitle(···)      //传入参数均省略
    .setMessage(···)   //传入参数均省略
    .setPositiveButton(···)  //传入参数均省略
    .setNegativeButton(···)  //传入参数均省略
    .create();

与前面介绍的Builder模式的一般用法相比,这省去Director类,使得Builder的使用更加简单、灵活。

用途

  1. 用于创建一些复杂的对象,比如对象创建时需要初始化设置的成员变量特别多,直接使用构造方法,那么传入的参数量将会非常长。用Builder模式就可以将对象创建过程分步进行,同时解决了JavaBean模式创建对象时在并发环境中的不一致性问题。
  2. 需要将创建的复杂对象的算法,独立于该对象的组成部分,也独立于组成部分的装配方法时。

参考资料

  1. http://www.cnblogs.com/devinzhang/archive/2012/01/06/2314670.html
  2. http://www.cnblogs.com/BeyondAnyTime/archive/2012/07/19/2599980.html
  3. Android API源码+官方开发文档
  4. Joshua Bloch著的书《Effective Java》
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值