目的:
如果你的对象相对复杂,那么就应该考虑对象的构建和它的表现相分离。目的是为了同样的构建过程可以创建不同的表示。

在android中我们创建dialog的时候就是建造者模式的最好体现。

AlertDialog alertDialog = new AlertDialog.Builder(getContext()).setView(new EditText(getContext())).create();

我们先来看看android源码中实现builder模式是如何实现的,这里我借鉴朋友的博客java设计模式——-Builder模式里面的一个构建复杂数据的例子来说明:

public class NutritionFacts {    private int servingSize = 0; // 食用份量    private int servings; // 份数    private int calories; // 卡路里    private int sodium; // 钠    private int fat; // 脂肪    private int carbohydrate; // 碳水化合物    public static class Builder {        private int servingSize = 0; // 食用份量        private int servings; // 份数        private int calories; // 卡路里        private int sodium; // 钠        private int fat; // 脂肪        private int carbohydrate; // 碳水化合物        public Builder(int servingSize, int servings) {            this.servingSize = servingSize;            this.servings = servings;        }        public Builder calories(int calories) {            this.calories = calories;            return this;        }        public Builder sodium(int sodium) {            this.servingSize = sodium;            return this;        }        public Builder fat(int fat) {            this.fat = fat;            return this;        }        public Builder carbohydrate(int carbohydrate) {            this.carbohydrate = carbohydrate;            return this;        }        public NutritionFacts show() {            return new NutritionFacts(this);        }    }    private NutritionFacts(Builder builder) {        servings = builder.servings;        servingSize = builder.servingSize;        calories = builder.calories;        carbohydrate = builder.carbohydrate;        fat = builder.fat;        sodium = builder.sodium;    }}

这就是类似android源码中dialog的builder模式,我们用这种方式去创建一个复杂的数据结构是非常简单和方便的。
调用方法:

 NutritionFacts nutritionFacts = new NutritionFacts                .Builder(20, 8)                .calories(20)                .carbohydrate(50)                .fat(60)                .show();

这个数据结构是不是很想android中new一个AlertDialog的写法?
我们去翻看AlertDialog源码你就会发现,其实是一模一样的写法。
这样得到的nutritionFacts实例你可以实现部分数据,也可以实现全部数据。

but!
如果你觉得这就是builder模式了,那你就太小看它的魅力了。
以上代码只是一个简单的示范,我要说的是builder模式的实现原理和工作方式。

在我看来以上这种builder模式是最简单的但并非最好的。
以上代码适合一个房子的建造,比如AlertDialog。如果你在建立一个AlertDialogA或者AlertDialogB。建立一个类似的房子的时候是不是需要重新写一个AlertDialogA或者AlertDialogB的代码呢?

所以,以上代码是有问题的。
第一,强耦合;
第二,必须声明静态;
第三,不符合开闭原则。

首相我们要搞清楚一个builder模式需要什么东西。
1,一个需要被建造出来的对象。比如房子。(dialog)
2,一个建造房子的工人。(builder)
3,指挥工程师如何建房子的工程师。比如指挥者。(director)
4,一个对象的建造,哪些是必须的,哪些是非必须的。就像一栋房子的房梁,墙体,房顶,这是必须的。但是贴瓷砖、建围墙、装修豪华这些是非必须的。

只要一个builder模式完成了这四个部分,那么你再造一栋房子,不用重复了,只需要在原来做过的这栋房子上稍加改造就行了。

具体看代码实现吧。

/** * 抽象建造者类,包含一个建造者必须建造的具体产品,还有一些制造产品的零件,零件不是必须的。 */public abstract class Builder {    public abstract void buildPartA();//零件a    public abstract void buildPartB();//零件b    public abstract void buildPartC();//零件c    public abstract Product getPart();//得到由建造者建造的具体产品}
/** * 建造者具体实现类 */public class ConcreteBuilderA extends Builder {    private Product product = new Product();    @Override    public void buildPartA() {        product.addPart("这个产品必须的零件a");        Log.i("test", "制造零件a");    }    @Override    public void buildPartB() {        product.addPart("这个产品必须的零件b");        Log.i("test", "制造零件b");    }    @Override    public void buildPartC() {        product.addPart("这个产品必须的零件b");        Log.i("test", "制造零件c");    }    //返回一个制造出来的具体产品    @Override    public Product getPart() {        return product;    }}
/** * 指挥者类 * 指挥者决定让建造者必须建造哪些零件 * 相当于指挥者对建造者说,房梁,墙体,房顶,必须建造 */public class Director {    public void cunstruct(Builder builder) {        builder.buildPartA();//创建零件a        builder.buildPartB();//创建零件B        //builder.buildPartC();//创建零件C,这栋房子不需要零件c    }}
/** * 产品类,由多个零件组成; * 一个产品可以添加很多的属性,这些属性不是必须的 * 就相当于一个基本完成的房子包含好多操作:刷墙,贴瓷砖,装修、建立围墙 * 这些操作不是必须的 */public class Product {    List<String> parts = new ArrayList<>();    public void addPart(String part) {        parts.add(part);    }    public void getPartTile(String title) {//得到由建造者建造的名称        Log.i("test", "设置产品标题");    }    public void getPartMessage(String message) {//得到由建造者建造的简介        Log.i("test", "设置产品介绍");    }    public Button getPartButton(Button button) {//得到由建造者建造的操作按钮        return button;    }    //将这个产品类展示出来,房子完工    public void show() {        for (String part : parts) {            Log.i("test", part);        }    }}

到这里。已经完工了。
1,抽象建造者控制必须建造的方法。(老板。这里的一切我说了算)
2,具体建造者(工人)执行建造。
3,指挥者(工程师)决定建造者建造哪些方法。
4,产品类。所有的老板,工人,工程师都是围绕着如何建立这个产品而生的。

我们来看看使用方法:

 Director director = new Director();//实例化一个指挥者        Builder builder = new ConcreteBuilderA();//实例化一个建造者        director.cunstruct(builder);//指挥者告诉建造者你必须要建造哪几个类,必须创建的类是抽象建造者中包含的抽象方法,而指挥者告诉建造者,这部分的抽象方法必须实现,因为这是必不可少的。        Product product = builder.getPart();//具体要建造的产品,它其中有很多方法,这些方法可以全部实现,也可以部分实现        product.addPart("非必需零件a");        product.addPart("非必需零件b");        product.getPartMessage("这是一个dialog");        product.getPartTile("dialog的标题");        product.getPartButton(new Button(context));        product.show();

这种builder比较复杂,但是它的确符合设计模式的六大原则。

如果你用这中方式创建一个AlertDialog。那么你同样可以用这中方式创建一个AlertDialogA或者更多类似的产品。

我们只需要在抽象建造者类中控制所有必须方法。
然后再创建一个工程师,称之为建造AlertDialogA的工程师,它告诉BuilderA(AlertDialogA的工人)建造AlertDialogA的必须方法。

再创建一个工人,称之为AlertDialogA的工人。完成工程师交代的任务。

最后,拿出ProductA产品的蓝图。

test,开工!

代码没有重复,没有修改原来建造的AlertDialog,相反拓展了AlertDialogA的创建方式。

这才是一个合格的或者说最好的设计模式实现方法。

这里要说明的一点是,并非android源码中用到的设计模式就是最终形态。它也只是在适合的场景用到了适合的设计模式。

它代表的是最合适的场景+最合适的代码方式;并非最好的设计模式的具体体现。

认清真相很重要,做对很重要。

更多相关文章

  1. android Activity 四大启动模式探究
  2. Activity中的四种启动模式
  3. Android Activity的四种加载模式
  4. JAVA数据结构及算法--Android中Activity的四种启动模式
  5. Android上的Open×××-TAP模式/策略路由
  6. Android飞行模式下Wifi开关行为的控制
  7. Android WindowManager的使用 & 添加 遮罩层 实现夜间模式
  8. Android情景模式、文件管理器 完整示例编程详解、Android程序优

随机推荐

  1. Android(安卓)Studio导入Android系统源码
  2. Android的Handler总结
  3. Eclipse中怎样安装Andriod ADT的插件
  4. Android(安卓)ViewGroup 触摸屏事件派发
  5. 探究Android中浏览器UA的生成策略
  6. Android(安卓)Framework内核之旅
  7. android WebView登录状态session id 和co
  8. android学习笔记之十一数据存储(Shared P
  9. Android(安卓)实现多个Audio文件的顺序播
  10. 自定义ViewPager实现图片自动轮播无限循