美文网首页
创建者设计模式

创建者设计模式

作者: shd踏尽桐影 | 来源:发表于2018-10-09 11:32 被阅读16次

Builder -创建者设计模式 是一种非常常见的设计模式,在安卓源码和第三方组件中经常可以见到:

边学编写 我将从以下几个方面整理

  • 一.概念
  • 二.使用场景,案例,标准写法,其他实现方法
  • 三.对比优缺点,总结

太长不看版本:
使用场景:当一个类较复杂,创建时候容易出问题或者不便于理解或者较复杂,希望规范化创建的时候使用创建者模式。
使用:对外通过导演类(规范流程)使用一个实现预期接口的建造者(builder)作为参数来进行创建,不同建造者可以创建不同对象,建造者中实现商业逻辑,最后返回一个造好的商品。导演类调用建造者逻辑,返回造好的商品。
优点:规范,对外方便简洁,利于扩展,内部逻辑可以自己把控。
缺点:如果内部逻辑过于复杂,需要创建很多数据类(Builder),得不偿失。

一、概念

(概念这个东西从来都是 开始看的不知所云或者总觉得很鸡肋的话,但是后来对问题有了深入了解就会发现很重要的的总结)
1 定义: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的展示。
2 Builder模式属于创建型,一步一步将一个复杂对象创建出来,允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程。

二、使用场景,案例

当我们阅读android源码时候会经常看到创造者模式,如常见的Dialog的创建

new AlertDialog.Builder(context)
.setIcon(R.drawable.navigation_empty_icon).
create();

而在我们实际工作中也经常会遇到这样需求:
由于业务需要创建一个很复杂的类的时候,需要多次创建一个类,并挨个对其属性进行赋值,在创建过程中往往还需要加入只有自己重读都费力的逻辑顺序,这样的代码无疑是十分丑陋和不规范的。而创建者设计模式可以解决这样的问题,那么我们根据什么条件来判断是否应该使用创建者设计模式呢?

  • 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
    需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
  • 对象的创建过程独立于创建该对象的类。在建造者模式中引入了指挥者类,将创建过程封装在-指挥者类中,而不在建造者类中。
  • 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。

这里使用另外一个例子进行讲解。
如一个学生类 由基本属性(年龄、姓名) 成绩属性(各科分数,总分数由各课分数之和得到 )

public class Student {
    传统方法
    private String name;
    private int age;
    private int totleGrade;
    private int mathGrade;
    private int chineseGrade;
     // 等等 …… 
}

传统方法
当我们需要创建这样一个对象时一般方法是2种: 1创建一个空对象使用set方法设置属性,2使用带参数构造方法传入参数。

Student student = new Student();
student.setName("张三");
student.setAge(12);
……

或者

public Student(String name, int age, ……){
this.name = name;
this.age = age;
……
}

这两种方法在数据量少并且逻辑简单的时候使用并没有什么问题,但是当我们成员多创建逻辑复杂时(比如总成绩为各科成绩之和),会增加学习成本并且不利于代码阅读和维护。

下面我们了解一下创建者模式:
创建者模式
1、Builder:给出一个抽象接口,规范建造者对于生产的产品的各个组成部分的建造。这个接口只是定一个规范,不涉及具体的建造,具体的建造让继承于它的子类(ConcreteBuilder)去实现。
2、ConcreteBuilder:实现builder接口,针对不同的商业逻辑,具体化各对象部分的建造,最后返回一个建造好的产品。
3、Director:导演,顾名思义,负责规范流程之用。在指导中不涉及产品的创建,只负责保证复杂对象各部分被创建或按某种顺序创建。
4、Product:复杂对象。
按照惯例,给出建造者模式的UML图(这个先记下来,非常有用,学一个设计模式,先把这个图记下来!)

创建者UML图

简单理解一下就是:

导演(Diector)根据大纲(Builder)写好的剧本(ConcreteBuilder) 拍出作品(Product)。

//1、Builder:给出一个抽象接口,规范建造者对于生产的产品的各个组成部分的建造。
// 这个接口只是定一个规范,不涉及具体的建造,具体的建造让继承于它的子类(ConcreteBuilder)去实现。
public interface Builder {
    void setName(); 
    void setAge();  
    void setMathGrade();    
    void setChineseGrade(); 
    Student build();
}
//ConcreteBuilder:实现builder接口,针对不同的商业逻辑,
// 具体化各对象部分的建造,最后返回一个建造好的产品。
public class BuilderXiaoZhang implements Builder {

    private Student student = new Student();

    @Override
    public void setName() {
        student.setName("xiaoZhang");
    }


    public void setAge() {
        student.setAge(14);
    }

    @Override
    public void setMathGrade() {
        student.setMathGrade(99);
    }


    public void setChineseGrade() {
        student.setChineseGrade(100);
    }

    @Override
    public Student build() {
        return student;
    }

}


//Product:复杂对象。
public class Student {
    private String name;
    private int age;
    private int mathGrade;
    private int chineseGrade;

   //省略setxxx() getxxx()方法
    public Student() {
    }
}

    //Director:导演,顾名思义,负责规范流程之用。
    //在指导中不涉及产品的创建,只负责保证复杂对象各部分被创建或按某种顺序创建。
    public class StudentRegistrar {
        private Builder builder;

        public StudentRegistrar(Builder builder) {
            this.builder = builder;
        }
        //产生产品,这里控制逻辑、顺序
        public Student construct(){
            builder.setName();
            builder.setAge();
            builder.setChineseGrade();
            builder.setMathGrade();
           return builder.build();
        }
    }

使用方法为

BuilderXiaoZhang builderXiaoZhang = new BuilderXiaoZhang();
Student stuZhang = new StudentRegistrar(builderXiaoZhang).construct();

我们可以看到导演类(StudentRegistrar )通过创建方法(construct())控制了复杂对象的赋值,外部调用者只需要创建合适的数据类(实现Builder接口)就可以实现复杂对象的创建。
契合了创建者设计模式的理念:

  • 在建造者模式中, 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
  • 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
  • 可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
  • 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
    变形
    但是我们以往见到的和通常希望的是不创建新类,仅通过合适的接口来进行属性赋值来完成创建工作如下
   public class Student {
        private String name;
        private int age;
        private int mathGrade;
        private int chineseGrade;

        //私有构造方法
        private Student() {
        }

        //builder接口 规范需要实现必要方法
        public interface Builder {
            Builder setName(String name);

            Builder setAge(int age);

            Builder setMathGrade(int mathGrade);

            Builder setChineseGrade(int chineseGrade);

            Student build();
        }

        //静态内部类
        public static class BuilderContrete implements Builder {
            private Student student;

            public BuilderContrete() {
                student = new Student();
            }


            @Override
            public Builder setName(String name) {
                student.name = name;
                return this;
            }

            @Override
            public Builder setAge(int age) {
                student.age = age;
                return this;
            }

            @Override
            public Builder setMathGrade(int mathGrade) {
                student.mathGrade = mathGrade;
                return this;
            }

            @Override
            public Builder setChineseGrade(int chineseGrade) {
                student.chineseGrade = chineseGrade;
                return this;
            }

            //返回设计结果类
            @Override
            public Student build() {
                return student;
            }
        }
    }

使用如下方法既可获得学生类

Student stu = new Student.BuilderContrete()
.setName("张三")
.setAge(14)
.build();

简单理解一下就是 小成本电影:

导演(Diector)自己写剧本(ConcreteBuilder)不要大纲(Builder)直接拍摄出作品(Product);

这样即满足了创建对象的灵活性,也在一定程度上节约了学习创建成本,链式的创建方法也清晰明了。

三.对比优缺点,总结

优点

  • 1.使用建造者模式可以使客户端不必知道产品内部组成的细节。
  • 2.具体的建造者类之间是相互独立的,对系统的扩展非常有利。
  • 3.由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。

缺点

  • 1.建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,例如很多组成部分都不相同,不适合使用建造者模式,因此其使用范围受到一定的限制。
  • 2.如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本。

不知别人怎么看待设计模式,我初看的时候仅仅感觉大部分是条条框框感觉将原本简单问题复杂化了,后来在看过很多优秀的代码后感觉自己代码在可读性、安全性、规范性等方面种种不足,渐渐理解优雅的代码,不仅仅是靠业务代码逻辑的缜密还有标准的命名锁紧等代码规范,而设计模式就是代码思想的规范,是有效而且必要的。

一直希望写点技术博客,今天算开了个头,希望自己坚持下去。最后如果有什么说的不对的地方,也希望大家指正。

相关文章

  • OkHttp的使用之设计模式

    使用的设计模式有: 创建者模式 策略模式 门面模式 责任链模式

  • 2. 设计模式与架构

    一、 设计模式 创建型模式抽象工厂模式(AbstractFactory)、工厂模式(Factory)、创建者模式(...

  • 设计模式问答(一)

    设计模式问答(一) 什么是设计模式?您能说出工厂模式、抽象工厂模式、创建者模式、原型模式、原型模式的潜复制及深复制...

  • 创建者设计模式

    Builder -创建者设计模式 是一种非常常见的设计模式,在安卓源码和第三方组件中经常可以见到: 边学编写 我将...

  • 设计模式-创建者模式总结

    创建者模式的特点及使用场景 《Effective Java》—— 创建与销毁对象 一章中有写道:当一个类中有大量的...

  • 设计模式-创建者(Builder)模式

    主要角色 具体创建者 职责 解决对象创建步骤多的问题 类图 代码 使用 技巧 建造者模式和模板方法很像。都是定义好...

  • 设计模式小结

    设计模式 7 大原则 创建型 单例模式 原型模式 创建者模式(生成器模式) 简单工厂模式 工厂方法模式 抽象工厂模...

  • 设计模式-创建者模式-单例模式

    零、 本文纲要 一、 单例模式 饿汉式① 静态变量方式② 静态代码块③ 枚举 懒汉式① 静态方法(线程不安全)② ...

  • 工厂模式 - 演示与场景

    UML类图: 代码模拟: 实例:React.createElement 工厂模式设计原则: 构造函数和创建者分离 ...

  • 设计模式简介

    开始写点东西,就从一直想好好融会贯通的设计模式写起吧.总所周知,设计模式分为三大块1 创建者模式2 结构性模式3 ...

网友评论

      本文标题:创建者设计模式

      本文链接:https://www.haomeiwen.com/subject/eebdaftx.html