一段对话讲完建造者模式

2023-10-09 22:40

本文主要是介绍一段对话讲完建造者模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

截止今天,小秋学习Java刚刚满三个月。此刻的小秋感觉自己Java学的还不错,想去帅地面前炫耀一番,于是,就发生了一下一番对话…

得意的小秋

帅地:嗨,小秋,看你今天气色不错啊。最近Java学的怎么样了?

小秋:说实话,比起三个月前我学指针的那段日子,这Java太友好了,感觉就是分分种的事(暗自得意)。

帅地:我靠,你这口气还挺大啊。从c的面向过程到Java的面向对象,还习惯不?

小秋:哎,还行,无非就是“一切皆对象”,Java中的对象感觉类似于C中的结构体。反正不过三七二十一,我脑子里都把他们当成是一个对象就得了。(内心自我感觉良好)

帅地:看你也学了三个月了,要不我随便拿道题考考你?(让你不谦虚,暗自偷笑)

小秋:好啊,正好练练手(嘿嘿,终于可以展现实力了)。

重载多次的构造函数

帅地:假如有一个蛋糕Cake对象,蛋糕这个对象有一个必选属性size,还有一些可选属性apple,banana,orange,mango等,必选属性代表用户必须要指定蛋糕的大小,可选属性代表这些蛋糕要加哪些材料。

小秋:这个很简单啊,创建一个Cake类,里面有size,apple,banana,orange,mango属性,然后构造器的参数里指定size这个参数就可以了。我直接上代码吧:

public class Cake {private int size;private String apple;private String banana;private String orange;private String mango;//new时必须给出sizepublic Cake(int size) {this.size = size;}
}

帅地:可选参数呢?我要new一个size=30,并且添加apple的蛋糕怎么办?

小秋:哦,我写的太快,忘了重载了,稍等(心想,这还不简单)。

public class Cake {private int size;private String apple;private String banana;private String orange;private String mango;public Cake(int size) {this.size = size;}public Cake(int size, String apple) {this.size = size;this.apple = apple;}public Cake(int size, String apple, String orange) {this.size = size;this.apple = apple;this.orange = orange;}public Cake(int size, String apple, String orange, String mango) {this.size = size;this.apple = apple;this.orange = orange;this.mango = mango;}
}

小秋:这下总可以了吧,你要加哪些料,你就使用哪个构造器。全部给你重载了。

帅地:(露出狡猾的表情)写构造函数倒是挺快的,那如果我要只加apple和mango的蛋糕呢?

小秋:啊?好吧,你这是逼我把所有组合的构造器都写出来。

于是,小秋把所有构造器的组合都写了出来。由于size是个必须参数,把其他四个可选参数进行组合,一共有16种。

噼里啪啦,劈里啪啦,小秋一口气把他们全部写出来了

public class Cake {private int size;private String apple;private String banana;private String orange;private String mango;public Cake(int size){this.size = size;}public Cake(int size, String apple){this.size = size;this.apple = apple;}public Cake(int size, String banana){this.size = size;this.banana = banana;}.....
}

小秋:好了,这下,你要啥组合有啥组合了。

帅地:四个可选参数你就写了这么一大堆参数了。确定这样写?

小秋:我觉得挺好的啊,反正很快,多写几个就多写几个吧。

帅地:那如果给你6个可选参数呢?

这时候小秋偷偷算了一些,发现一共有74种组合?

小秋:不就是74种组合,我觉得问题不是很大(心有点虚)。

帅地:那万一有10个可选参数呢?

小秋:…

帅地:而且你重载那么多构造器,用户在在new的时候,第一个参数和第二个参数代表什么,用户混乱了怎么吧?例如,你有个apple+banana的构造器

public Cake(int size, String apple, String banana){this.size = size;this.apple = apple;this.banana = banana;
}

但是用户在new的时候,可能忘记了参数的顺序

Cake cake = new Cake(size,“banana”,“apple”)

小秋:我会提供相应的文档啊,忘记了可以看文档勒。

帅地:几百个构造函数,而且还那么相似,你去看下文档试试,然后说说你的心情。

小秋:…(不知所措)。

通过Javabean的模式

帅地:有没其他什么办法?

小秋:我想到另一种办法了,我可以通过set和get方法来设置可选参数的。我直接上代码你看看

public class Cake {private int size;private String apple;private String banana;private String orange;private String mango;public Cake(int size) {this.size = size;}//通过set来添加材料public void setApple(String apple) {this.apple = apple;}public void setBanana(String banana) {this.banana = banana;}public void setMango(String mango) {this.mango = mango;}public void setOrange(String orange) {this.orange = orange;}
}

此时的小秋有点得意…

帅地:挺不错,这种方法比刚才的好多了,又简洁。

此时如果要new一个apple+orange+mango的蛋糕的话,代码如下:

Cake cake = new Cake(30);
cake.setApple("apple");
cake.setOrange("orange");
cake.setMange("mange");
参数依赖检查问题

帅地:这种方法也是有缺点,例如用构造器重载时一行代码就可以搞定了,现在要用四行代码。

小秋:反正我觉得这样很nice(得意中…)。

帅地:不过这样写有一个致命的缺点,假如那些属性之间存在依赖性的话,怎么办?例如Cake多了A,B两个属性,并且这两个属性之间存在依赖关系。如果你设置了属性A,但是没有设置属性B,那么这个Cake对象就会出问题。或者属性的先后顺序设置也可能会导致出现问题。对于这种情况,你在什么地方检查这种相互依赖的逻辑?

小秋:有点蒙蔽,不知所措…。

小秋:那你说怎么办?

静态内部类

帅地:其实你已经做的相当不错了,不过我今天就教你另外一个办法,我们可以开放一个静态内部类专门用来与外界打交道,用来收集用户想要设置的属性并且做检查。直接上代码:

public class Cake {private int size;private String apple;private String banana;private String orange;private String mango;//private,让外面无法直接创建private Cake(Builer builer) {this.size = builer.size;this.apple = builer.apple;.....}//专门用来与外界打交道public static class Builer {private int size;private String apple;private String banana;private String orange;private String mango;public void setSize(int size) {this.size = size;}//为了省点代码,其他的省略public Cake build() {//检查参数之间的依赖关系是否正确return new Cake(this);}.....}
}

假如我要new一个apple+orange的Cake

Cake.Builer builer = new Cake.Builer();
builer.setSize(30);
builer.setApple("apple");
builer.setOrange("orange");
//创建一个蛋糕
Cake cake = builer.build();

帅地:这种方法牛吧?这还不够,我们还可以采用链式调用的方法。

链式调用
public class Cake {private int size;private String apple;private String banana;private String orange;private String mango;//private,让外面无法直接创建private Cake(Builer builer) {this.size = builer.size;this.apple = builer.apple;.....}//专门用来与外界打交道public static class Builer {private int size;private String apple;private String banana;private String orange;private String mango;//返回参数改为Builerpublic Builer setSize(int size) {this.size = size;return this;}public Builer setApple(String apple) {this.apple = apple;return this;}//为了省点代码,其他的省略public Cake build() {//检查参数之间的依赖关系是否正确return new Cake(this);}}
}

如何使用?

Cake cake = new Cake.Builer().setSize(30).setApple("apple").setOrange("orange").build();

一行代码就搞定了。

帅地:厉害吧?

小秋:涨知识了,看来我还是太年轻了,以后得好好向帅地学习。

建造者模式

帅地:其实,上面那种方法算是23种设计模式中的其中一种—建造者模式。不过这只是一个简化版的建造者模式。

对于建造者模式,具体的UML图是这样的:

在这个UML图中,Builder是一个接口,定义一套规范,而我们使用的例子中,没有使用接口,直接使用具体类,但核心思想还是一样的。

其核心思想就是:将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

小秋:哇,强啊。我要给你点赞…

算是第二次采取对话的方式写…,以后会多采取这种方式来写勒。

关注公我的众号:苦逼的码农,获取更多原创文章,后台回复礼包送你一份时下热门的资源大礼包。同时也感谢把文章介绍给更多需要的人

这篇关于一段对话讲完建造者模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/176070

相关文章

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

模版方法模式template method

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/template-method 超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 上层接口有默认实现的方法和子类需要自己实现的方法

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

迭代器模式iterator

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/iterator 不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素

《x86汇编语言:从实模式到保护模式》视频来了

《x86汇编语言:从实模式到保护模式》视频来了 很多朋友留言,说我的专栏《x86汇编语言:从实模式到保护模式》写得很详细,还有的朋友希望我能写得更细,最好是覆盖全书的所有章节。 毕竟我不是作者,只有作者的解读才是最权威的。 当初我学习这本书的时候,只能靠自己摸索,网上搜不到什么好资源。 如果你正在学这本书或者汇编语言,那你有福气了。 本书作者李忠老师,以此书为蓝本,录制了全套视频。 试

利用命令模式构建高效的手游后端架构

在现代手游开发中,后端架构的设计对于支持高并发、快速迭代和复杂游戏逻辑至关重要。命令模式作为一种行为设计模式,可以有效地解耦请求的发起者与接收者,提升系统的可维护性和扩展性。本文将深入探讨如何利用命令模式构建一个强大且灵活的手游后端架构。 1. 命令模式的概念与优势 命令模式通过将请求封装为对象,使得请求的发起者和接收者之间的耦合度降低。这种模式的主要优势包括: 解耦请求发起者与处理者

springboot实战学习(1)(开发模式与环境)

目录 一、实战学习的引言 (1)前后端的大致学习模块 (2)后端 (3)前端 二、开发模式 一、实战学习的引言 (1)前后端的大致学习模块 (2)后端 Validation:做参数校验Mybatis:做数据库的操作Redis:做缓存Junit:单元测试项目部署:springboot项目部署相关的知识 (3)前端 Vite:Vue项目的脚手架Router:路由Pina:状态管理Eleme

状态模式state

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/state 在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。 在状态模式中,player.getState()获取的是player的当前状态,通常是一个实现了状态接口的对象。 onPlay()是状态模式中定义的一个方法,不同状态下(例如“正在播放”、“暂停

软件架构模式:5 分钟阅读

原文: https://orkhanscience.medium.com/software-architecture-patterns-5-mins-read-e9e3c8eb47d2 软件架构模式:5 分钟阅读 当有人潜入软件工程世界时,有一天他需要学习软件架构模式的基础知识。当我刚接触编码时,我不知道从哪里获得简要介绍现有架构模式的资源,这样它就不会太详细和混乱,而是非常抽象和易

使用Spring Boot集成Spring Data JPA和单例模式构建库存管理系统

引言 在企业级应用开发中,数据库操作是非常重要的一环。Spring Data JPA提供了一种简化的方式来进行数据库交互,它使得开发者无需编写复杂的JPA代码就可以完成常见的CRUD操作。此外,设计模式如单例模式可以帮助我们更好地管理和控制对象的创建过程,从而提高系统的性能和可维护性。本文将展示如何结合Spring Boot、Spring Data JPA以及单例模式来构建一个基本的库存管理系统