深入理解Java设计模式之建造者模式
作者:一指流砂~ 发布时间:2022-12-06 00:57:37
一、什么是建造者模式
建造者模式也称生成器模式 定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示(依赖倒转)
产品类:一般是一个较为复杂的对象,也就是说创建对象的过程比较复杂,一般会有比较多的代码量。在本类图中,产品类是一个具体的类,而非抽象类。实际编程中,产品类可以是由一个抽象类与它的不同实现组成,也可以是由多个抽象类与他们的实现组成。
抽象建造者:引入抽象建造者的目的,是为了将建造的具体过程交与它的子类来实现。这样更容易扩展。一般至少会有两个抽象方法,一个用来建造产品,一个是用来返回产品。
建造者:实现抽象类的所有未实现的方法,具体来说一般是两项任务:组建产品;返回组建好的产品。
指挥类:负责调用适当的建造者来组建产品,指挥类一般不与产品类发生依赖关系,与指挥类直接交互的是建造者类。一般来说,指挥类被用来封装程序中易变的部分。
二、建造者模式的应用场景
1.创建复杂对象的算法独立于组成对象的部件
2.同一个创建过程需要有不同的内部表象的产品对象
例子:建房子,不管建什么房子,它们都离不开地基、柱子、层面和墙体这些组成部分,建筑工人就是把这些组成部分一个个建起来,最后连成一体建出一栋栋楼房。
三、建造者模式的优缺点
优点
1.客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
2.每一个具体建造者都独立,因此可以方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象 。
3.可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
4.增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭”。
缺点
1.当建造者过多时,会产生很多类,难以维护。
2.建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,若产品之间的差异性很大,则不适合使用该模式,因此其使用范围受到一定限制。
3.若产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
四、工厂模式和建造者模式的对比
工厂模式用于处理 如何获取实例对象 问题,建造者模式用于处理如何建造实例对象 问题
建造者模式与工厂模式是极为相似的,总体上,建造者模式仅仅只比工厂模式多了一个“指挥类”的角色。在建造者模式的类图中,假如把这个指挥类看做是最终调用的客户端,那么剩余的部分就可以看作是一个简单的工厂模式了。
与工厂模式相比,建造者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类——指挥类。
也就是说,工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;而建造者模式中,建造者类一般只提 * 品类中各个组件的建造,而将具体建造过程交付给指挥类。由指挥类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。
五、建造者模式的实现
Product
类---产品类,由多个部件组成
//Product类,由多个部件组成
public class Product
{
List<string> parts = new List<string>();
//添加产品部件
public void Add(string part)
{
parts.Add(part);
}
public void show()
{
Console.WriteLine("\n 创建产品");
foreach (var item in parts)
{
Console.WriteLine("item");
}
}
}
Builder
类---抽象建造者类,确定产品由两个部件PartA和PartB组成,并声明一个得到产品建造后结果的方法GetResult
abstract class Builder
{
public abstract void BuilderPartA();
public abstract void BuilderPartB();
public abstract Product GetResult();
}
具体建造者类
//ConcreteBuilder1类---具体建造者类
class ConcreteBuilder1 : Builder
{
private Product product = new Product();
//建造具体的两个部件
public override void BuilderPartA()
{
product.Add("部件A");
}
public override void BuilderPartB()
{
product.Add("部件B");
}
public override Product GetResult()
{
return product;
}
}
//ConcreteBuilder2类---具体建造者类
class ConcreteBuilder2 : Builder
{
private Product product = new Product();
//建造具体的两个部件
public override void BuilderPartA()
{
product.Add("部件X");
}
public override void BuilderPartB()
{
product.Add("部件Y");
}
public override Product GetResult()
{
return product;
}
}
Director
类---指挥者类
class Director
{
public void Construct(Builder builder)
{
//用来指挥建造过程
builder.BuilderPartA();
builder.BuilderPartB();
}
}
客户端代码---客户不需知道具体的建造过程
static void Main(string[] args)
{
Director director = new Director();
Builder b1 = new ConcreteBuilder1();
Builder b2 = new ConcreteBuilder2();
//指挥者用ConcreteBuilder1方法建造产品
director.Construct(b1);
Product p1 = b1.GetResult();
p1.show();
//指挥者用ConcreteBuilder2方法建造产品
director.Construct(b2);
Product p2 = b2.GetResult();
p2.show();
Console.Read();
}
六、总结
建造者模式的使用场合是当创建复杂对象时,把创建对象成员和装配方法分离出来,放在建造者类中去实现,用户使用该复杂对象时,不用理会它的创建和装配过程,只关心它的表示形式。
其实完全理解这个模式还是要一番思考的,难以搞懂的是指挥者似乎没什么存在的必要,在代码里也没体现它的作用,我们也可以把指挥者的方法放在建造者里面,但为什么没有这样做呢?我想这可能是考虑到单一责任原则,建造者只负责创建对象的各个部分,至于各个部分创建的顺序、装配方法它就不管了。还有就是当顺序要改变时,建造者可以不用改动,改动指挥者就好了,指挥者只有一个,建造者有很多,要改建造者就麻烦了。
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!
来源:https://www.cnblogs.com/xuwendong/p/9792646.html
猜你喜欢
- Java为什么不浪(long)学而时习之不亦说乎,继续温习Java。今天使用switch时,不小心写了如下代码,报错如下。 public s
- 本文实例为大家分享了java实现递归菜单树的具体代码,供大家参考,具体内容如下1.表结构SET FOREIGN_KEY_CHECKS=0;-
- 1.OkHttp发起网络请求可以通过OkHttpClient发起一个网络请求//创建一个Client,相当于打开一个浏览器 OkHttpCl
- 标题index界面加载问题刚开始学习springBoot记录一下遇到的小问题1.index.html加载不出来的问题我习惯性的将index.
- 用途项目中使用了 dubbo,注册中心使用的 zookeeper,使用 zookeeper 实现了一个简单的分布式锁(依赖 curator)
- 本Demo使用三个类一个Test类一个自定义的Stack类一个自定义的Queue类可以实现的功能:1.对于一个写在文本文件中的迷宫,能够将其
- 通用配置#下面介绍的整合JDBC和整合MyBatis都需要添加的实体类和配置数据库表#CREATE TABLE `user` ( `id`
- 本文实例为大家分享了Android绝对布局AbsoluteLayout的具体代码,供大家参考,具体内容如下1>AbsoluteLayo
- IDEA 2020.1 版自动导入MAVEN依赖的方法(新版MAVEN无法自动导入/更新POM依赖、MAVEN设置自动更新、自动更新快捷键)
- 前言《飞机大战-I》是一款融合了街机、竞技等多种元素的经典射击手游。华丽精致的游戏画面,超炫带感的技能特效,超火爆画面让你肾上腺素爆棚,给你
- 有时候,我们需要制作一个Word模板文档,然后发给用户填写,但我们希望用户只能在指定位置填写内容,其他内容不允许编辑和修改。这时候我们就可以
- 对于生成的sql语句 自动加上单引号的情况mybatis是这样的,如果表的字段跟系统字段冲突,写sql语句的时候必须得加上单引号,这样才会区
- BeanUtilsBeanUtils是Apache commens组件里面的成员,由Apache提供的一套开源api,用于简化对javaBe
- 在JavaWeb的相关开发中经常会涉及到多级菜单的展示,为了方便菜单的管理需要使用数据库进行支持,本例采用相关算法讲数据库中的条形记录进行相
- 在该示例中,阐述了SpringMVC如何上传文件。1、上传页面upload.jsp<body> <form
- jmap:Java内存映像工具jmap(Memory Map for Java)命令用于生成堆转储快照(一般称为heapdump或dump文
- 本文实例讲述了Java编程使用箱式布局管理器。分享给大家供大家参考,具体如下:先来看看运行效果:完整代码如下:package awtDemo
- 目录前言1、饿汉式(线程安全)⭐2、懒汉式(线程不安全)⭐3、懒汉式(加锁)4、懒汉式(双重校验锁)⭐5、单例模式(静态内部类)6、单例模式
- 使用注解来配置Action可以实现零配置,零配置将从基于纯XML的配置转化为基于注解的配置。使用注解,可以在大多数情况下避免使用
- 在平常工作中我们经常会遇到maven引用的jar包冲突的事情,这时候我们就需要找出冲突的包,并将低版本或者缺少某些方法的jar给剔除掉。这个