热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

设计模式01创建型模式-建造者模式(BuildPattern)

参考1.BuilderDesignPattern|Youtube2.建造者模式(Builder和Director)|博客园3.深入理解Builder模式|简书
参考

1. Builder Design Pattern | Youtube

2. 建造者模式(Builder和Director)| 博客园

3. 深入理解Builder模式 | 简书

 

建造者模式(Builder Pattern)

将一个复杂对象的构建与表示分离,使得同样的构建过程可以不同的表示。

通常,在建造者Builder中包含多个不同的属性(基本类型或者别的类对象),这些属性由Builder的方法构建,由Director来组装出一种产品Product。 也就是说,Builder Pattern的目的是为了构建一个或多个Product,不同的构建过程可以表示不同Product。每一个Builder至少代表了一种不同属性的组合,以组装成产品。

 

组成 

Builder 为创建一个Product对象的各个部件指定的抽象接口
ConcreteBuilder 

实现Builder接口,构造和装配Product产品的各个部件;

定义并明确所创建的表示;

提供一个获取Product的接口。

Director 构造一个使用Builder接口对象
Product

被构造的复杂对象;

由ConcreteBuilder内部表示和定义它的装配过程;

包含了组成部件/属性的类,包括将这些部件装配成最终产品的接口。

 

适用场景

[参考1~2]:建造者模式用于创建的Product对象,由其他多个对象组成。

1)当你想建造的对象由其他对象(称为部件)组成;

2)当你想这些组件的创建独立于主要对象;

3)隐藏来自client的部分的创建,以至于这部分和创建对象是相互独立的;

4)建造者知道细节,并且别人不知道;

通俗讲,当自己想创建的对象由多个其他类对象组成,并且希望自己创建的对象独立于其他对象的创建,用户不必知道创建这个对象的细节,只需要指定特定Builder来负责建造组件、Director负责何时组装以及如何组装即可。

 

特点

1) 分步构建一个复杂对象。Product通常由别的多个不同的子对象组成,builder提供构建接口和获取最终产品对象的接口。

2) 支持多种构建表示。Builder模式封装了构建的过程,用户只需传入关心的参数和必须的参数,而不用关心复杂的构建过程,就能创建出不同的表示。

3) 将部件的创建和部件的组装方式解耦,部件类型和部件装配方式互不影响。

 

缺点

1) 不适合包含同类别子对象的Product创建,如组合模式;

2) 当Product增加部件时,可能会导致Builder及其子类, Director的大量修改;

 

与工厂模式,抽象工厂比较

工厂模式:提供统一的抽象接口,让子类决定实例化哪一个类,使对象的初始化延迟到子类进行。

抽象工厂:为创建一组相关或者相互依赖的对象提供一个接口,而无需指定他们具体的类。

 

1. 建造者 vs 工厂模式

工厂模式通常只生产一种产品,而且产品之间没有必然联系。侧重于表示接口和Product之间的关系。

建造者模式可以产生一种或多种产品表示,不同的构建过程可以表示不同Product。侧重于用多个部件构建复杂产品表示的过程。

 

2. 建造者 vs 抽象工厂

抽象工厂往往产出多个Product,并且Product之间存在一定关联或依赖关系。每个具体Product要求用工厂来创建。抽象工厂的具体工厂生产产品,可以用Builder模式来创建。侧重于表示一组方案。

建造者模式通常产生1个产品,不同的构建过程有不同的Product表示。侧重于表示1个复杂产品的构建的过程。

 

通用类图

 Figure1 Builder Pattern通用类图

 

demo 

下面这个例程跟网上流传的“造人”"造船"例程很像,能体现Builder模式的基本特点,“将对象的创建与表示分离”。但是有一个缺点,就是一个Builder只能生产一种产品对象,因为产品组件在Builder中的创建已经固化了,当需要添加一种对象时,就需要添加一种Builder。

[参考1] Client要创建Robot,就需要通过RobotBuilder创建OldStyleRobotBuilder,然后再创建RobotEngineer(Robot工程师),在RobotEngineer通过RobotPlan(Robot设计)创建Robot对象。创建过程如Figure2.

 

Figure2 Client创建Robot过程

 

 

Figure3 demo的UML类图

 

代码

 1. 创建Robot接口RobotPlan,定义各属性设置的公共方法

RoboPlan.java

public interface RobotPlan {
    
    public void setHead(String head);
    
    public void setTorso(String torso);
    
    public void setArms(String arms);
    
    public void setLegs(String legs);
}

 

2.定义Robot,实现RobotPlan接口,这里的几个属性用String类型

Robot.java

public class Robot implements RobotPlan {
    private String head;
    private String torso;
    private String arms;
    private String legs;

    @Override
    public void setHead(String head) { this.head = head; }
    
    public String getHead() { return head; }

    @Override
    public void setTorso(String torso) { this.torso = torso; }
    
    public String getTorso() { return torso; }
    
    @Override
    public void setArms(String arms) { this.arms = arms; }

    public String getArms() { return arms; }
    
    @Override
    public void setLegs(String legs) { this.legs = legs; }
    
    public String getLegs() { return legs; }
}

 

3.定义Robot的Builder 接口RobotBuilder,声明构建Robot子对象/属性的公共方法,读取Robot的方法

RobotBuilder.java

public interface RobotBuilder {
    
    public void buildHead();
    
    public void buildTorso();
    
    public void buildArms();
    
    public void buildLegs();
    
    public Robot getRobot();
}

 

4.定义OldStyleRobotBuilder,实现接口RobotBuilder,负责具体构建Robot的子对象/属性

OldStyleRobotBuilder.java

/* 将robot各子部件固化到builder中 */
public class OldStyleRobotBuilder implements RobotBuilder {

    private Robot robot;
    
    public OldStyleRobotBuilder(){
        robot = new Robot();
    }
    
    @Override
    public void buildHead() {
        robot.setHead("Tin Head");
    }

    @Override
    public void buildTorso() {
        robot.setTorso("Tin Torso");
    }

    @Override
    public void buildArms() {
        robot.setArms("Blowtorch Arms");
    }

    @Override
    public void buildLegs() {
        robot.setLegs("Roller Legs");
    }

    @Override
    public Robot getRobot() {
        return robot;
    }

}

 

5. 定义Director RobotEngineer,指导RobotBuilder构建Robot

RobotEngineer.java

/* 指导RobotBuilder构建Robot*/
public class RobotEngineer {
    private RobotBuilder robotBuilder;
    
    public RobotEngineer (RobotBuilder robotBuilder){
        this.robotBuilder = robotBuilder;
    }
    
    public void makeRobot(){
        robotBuilder.buildHead();
        robotBuilder.buildTorso();
        robotBuilder.buildArms();
        robotBuilder.buildLegs();
        
        // 另外一种方式是在此处创建Robot, 然后将build构建的结果复制给Robot
    }
    
    public Robot getRobot(){
        return robotBuilder.getRobot();
    }
}

 

6. RobotBuilderDemo(Client)测试例程

1) 第一步是创建RobotBuilder具体对象

2) 第二步是创建Director RobotEngineer,用于指导构建Robot

3) 第三步是制造/组装Robot

4) 第四步是测试组装的Robot属性

public class RobotBuilderDemo {

    public static void main(String[] args){
        RobotBuilder robotBuilder = new OldStyleRobotBuilder();
        RobotEngineer robotEngineer = new RobotEngineer(robotBuilder);
        robotEngineer.makeRobot();
        
        Robot robot = robotEngineer.getRobot();
        System.out.println("Robot build component:");
        System.out.println("Robot Head: "+robot.getHead());
        System.out.println("Robot Torso: "+robot.getTorso());
        System.out.println("Robot Arms:"+robot.getArms());
        System.out.println("Robot Legs:"+robot.getLegs());
    }
}

 

7. 运行结果

 

总结

1. 产品的参数往往由外部Client来决定,因此可以将Builder中构建Product属性的方法设为由外部参数决定。

例如,public void buildHead(); 可修改为public void buildHead(String head)

 


推荐阅读
  • 本文整理了Java中com.evernote.android.job.JobRequest.getTransientExtras()方法的一些代码示例,展示了 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文概述了JNI的原理以及常用方法。JNI提供了一种Java字节码调用C/C++的解决方案,但引用类型不能直接在Native层使用,需要进行类型转化。多维数组(包括二维数组)都是引用类型,需要使用jobjectArray类型来存取其值。此外,由于Java支持函数重载,根据函数名无法找到对应的JNI函数,因此介绍了JNI函数签名信息的解决方案。 ... [详细]
  • C#设计模式之八装饰模式(Decorator Pattern)【结构型】
    一、引言今天我们要讲【结构型】设计模式的第三个模式,该模式是【装饰模式】,英文名称:DecoratorPattern。我第一次看到这个名称想到的是另外一个词语“装修”,我就说说我对“装修”的理 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • GreenDAO快速入门
    前言之前在自己做项目的时候,用到了GreenDAO数据库,其实对于数据库辅助工具库从OrmLite,到litePal再到GreenDAO,总是在不停的切换,但是没有真正去了解他们的 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 点击上方“新机器视觉”,选择加”星标”或“置顶”重磅干货,第一时间送达很早就想总结一下前段时间学习HALCON的心得,但由于其他的事情总是抽不出时间。去年有过一段时间的集中学习,做 ... [详细]
  • 装饰模式(Deocrator)     动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。    所谓装饰,就是一些对象给主题 ... [详细]
author-avatar
2859731843_3e4a5d
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有