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

设计模式系列之如何使用建造者模式

这篇文章主要讲解了“设计模式系列之如何使用建造者模式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来

这篇文章主要讲解了“设计模式系列之如何使用建造者模式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“设计模式系列之如何使用建造者模式”吧!

 1、概述

建造者模式是一种创建型设计模式, 使你能够分步骤创建复杂对象。该模式允许你使用相同的创建代码生成不同类型和形式的对象。

2、适用场景

1)避免重叠构造函数,例如:一个类有很多的属性,这时候的构造方法需要传递很多的参数,为了避免这样,会重新写一个相对参数较少的构造方法,但是仍然需要对其他参数进行赋默认值。

2)当需要创建不同的产品类型,此处指比较接近的产品类型,则可以在顶层builder中包含大部分产品属性的赋值方法。

3、实例

有以下场景,我们分别使用常规方式和建造者模式实现:

当前有一个汽车工厂,可以生产的汽车类型有ordinary,sport。 除了汽车之外,同样可以生产汽车的操作手册manual。 汽车有以下的属性: 1、type 类型 2、seats 座位数 3、engine 引擎 4、GPS 导航  分别实现汽车和手册的生产过程

不使用建造者模式

分别创建车car和手册manual,以及其内部的属性,当前例子中车和手册是相同的属性。

@Data public class Car {      private CarType type;      private int seats;      private Engine engine;      private GPS GPS;      public Car(CarType type, int seats, Engine engine, com.cloud.bssp.designpatterns.builder.withouttdesign.entity.GPS GPS) {         this.type = type;         this.seats = seats;         this.engine = engine;         this.GPS = GPS;     }      public void detail() {         System.out.println("this is " + type + " car");         System.out.println("the seats is :" + seats);         System.out.println("the engine is :" + engine);         System.out.println("this GPS is :" + GPS);     } }
@Data public class Manual {      private CarType type;      private int seats;      private Engine engine;      private GPS GPS;      public Manual(CarType type, int seats, Engine engine, com.cloud.bssp.designpatterns.builder.withouttdesign.entity.GPS GPS) {         this.type = type;         this.seats = seats;         this.engine = engine;         this.GPS = GPS;     }      public void detail() {         System.out.println("this is " + type + " car");         System.out.println("the seats is :" + seats);         System.out.println("the engine is :" + engine);         System.out.println("this GPS is :" + GPS);     } }
public enum CarType {     SPORT,ORDINARY; }
/**  * 汽车引擎  */ @Data public class Engine {      /**      * 排量      */     private final double volume;     /**      * 里程      */     private double mileage;      public Engine(double volume, double mileage) {         this.volume = volume;         this.mileage = mileage;     } }
@Data public class GPS {     /**      * 路线      */     private String route;      public GPS(String route) {         this.route = route;     } }

测试类:

/**  * 客户端  */ @RunWith(SpringRunner.class) @SpringBootTest(classes = TestApplication.class) public class TestDemo {      @Test     public void test() {         //生产跑车         Car sportCar = new Car(                 CarType.SPORT,                 2,                 new Engine(3.0, 0),                 new GPS("上海东方明珠塔到上海动物园")         );         sportCar.detail();         System.out.println("----------------------------------------");         //生产普通汽车         Car ordinaryCar = new Car(                 CarType.ORDINARY,                 4,                 new Engine(2.0, 0),                 new GPS("上海东方明珠塔到上海动物园")         );         ordinaryCar.detail();         System.out.println("----------------------------------------");         //生产汽车操作手册         Manual manual = new Manual(                 CarType.ORDINARY,                 4,                 new Engine(2.0, 0),                 new GPS("上海东方明珠塔到上海动物园")         );         manual.detail();         System.out.println("----------------------------------------");     } }

结果:

this is SPORT car the seats is :2 the engine is :Engine(volume=3.0, mileage=0.0) this GPS is :GPS(route=上海东方明珠塔到上海动物园) ---------------------------------------- this is ORDINARY car the seats is :4 the engine is :Engine(volume=2.0, mileage=0.0) this GPS is :GPS(route=上海东方明珠塔到上海动物园) ---------------------------------------- this is ORDINARY car the seats is :4 the engine is :Engine(volume=2.0, mileage=0.0) this GPS is :GPS(route=上海东方明珠塔到上海动物园) ----------------------------------------

使用建造者模式实现

使用建造者模式后,代码要比上面的方法多了不少:

设计模式系列之如何使用建造者模式

创建顶层Builder

public interface Builder {      void setCarType(CarType carType);      void setSeats(int seats);      void setEngine(Engine engine);      void setGPS(GPS gps); }

创建实体类,与上面是相同的,这里不重复了。

创建car的builder:

@Data public class CarBuilder implements Builder {      private CarType carType;      private int seats;      private Engine engine;      private GPS GPS;      public Car getResult() {         return new Car(carType, seats, engine, GPS);     } }

创建汽车操作手册builder:

@Data public class ManualBuilder implements Builder {      private CarType carType;      private int seats;      private Engine engine;      private GPS GPS;      public Manual getResult() {         return new Manual(carType, seats, engine, GPS);     } }

创建一个builder管理器:

public class Director {      public void constructSportsCar(Builder builder) {         builder.setCarType(CarType.SPORT);         builder.setSeats(2);         builder.setEngine(new Engine(3.0, 0));         builder.setGPS(new GPS("上海东方明珠塔到上海动物园"));     }      public void constructOrdinaryCar(Builder builder) {         builder.setCarType(CarType.ORDINARY);         builder.setSeats(4);         builder.setEngine(new Engine(2.0, 0));         builder.setGPS(new GPS("上海东方明珠塔到上海动物园"));     } }

测试类:

@RunWith(SpringRunner.class) @SpringBootTest(classes = TestApplication.class) public class TestDemo {      @Test     public void test() {         Director director = new Director();         //生产跑车         CarBuilder carBuilder = new CarBuilder();         director.constructSportsCar(carBuilder);         Car sportCar = carBuilder.getResult();         sportCar.detail();         System.out.println("-----------------------------------");          //生产普通汽车         director.constructOrdinaryCar(carBuilder);         Car ordinaryCar = carBuilder.getResult();         ordinaryCar.detail();         System.out.println("-----------------------------------");          //生产汽车操作手册         ManualBuilder manualBuilder = new ManualBuilder();         director.constructOrdinaryCar(manualBuilder);         Manual manual = manualBuilder.getResult();         manual.detail();         System.out.println("-----------------------------------");     } }

结果:

this is SPORT car the seats is :2 the engine is :Engine(volume=3.0, mileage=0.0) this GPS is :GPS(route=上海东方明珠塔到上海动物园) ----------------------------------- this is ORDINARY car the seats is :4 the engine is :Engine(volume=2.0, mileage=0.0) this GPS is :GPS(route=上海东方明珠塔到上海动物园) ----------------------------------- this Manual ORDINARY car the Manual seats is :4 the Manual engine is :Engine(volume=2.0, mileage=0.0) this GManual PS is :GPS(route=上海东方明珠塔到上海动物园) -----------------------------------

4、分析

建造者模式基本有以下几个角色:

设计模式系列之如何使用建造者模式

如上面两种方式的结果显示,都可以实现生产汽车和汽车手册。

结果没什么差异。

在没使用建造者的方式中:

生产汽车的参数是由客户端自己指定的,并且需要传很多的参数,实际工作中可能需要更多的参数,可能有部分参数是不需要的。

使用建造者模式

用户不需要去具体指定多个参数了,对于客户端更友好。

builder:将产品new()提出到builder中,提供产品所拥有的属性设置方法,一类产品都可以使用这个builder进行产品创建。

director:作为builder的管理者,主要控制产品的属性设置,在这个类中,具体指定除了可以生产的产品的构造,并且对属性进行赋值,最终返回一个用户需要的builder。

客户端调用只需要创建需要的产品类型builder,通过管理者director对builder进行属性设置,最终客户端通过调用builder的方法获取最终需要的产品。

极大程度减少并优化的客户端的代码,同时由管理者director限制了产品的种类。

从扩展层层面看:

未使用建造者:增加对应的产品类,客户端直接new。

使用建造者模式:增加builder,并且在director增加可创建的产品的builder构造。

5、总结

最后总结下上面例子中使用抽象工厂方法的优缺点:

优点:

1)遵守单一原则。

2)不同产品,可复用相同的产品创建流程。

3)简化客户端调用方式。去除多参构造的方式。

4)分步骤创建对象。

缺点:

增加多个类,代码复杂度增加。

感谢各位的阅读,以上就是“设计模式系列之如何使用建造者模式”的内容了,经过本文的学习后,相信大家对设计模式系列之如何使用建造者模式这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程笔记,小编将为大家推送更多相关知识点的文章,欢迎关注!


推荐阅读
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • Spring学习(4):Spring管理对象之间的关联关系
    本文是关于Spring学习的第四篇文章,讲述了Spring框架中管理对象之间的关联关系。文章介绍了MessageService类和MessagePrinter类的实现,并解释了它们之间的关联关系。通过学习本文,读者可以了解Spring框架中对象之间的关联关系的概念和实现方式。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
author-avatar
手机用户2502872795
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有