24种设计模式-生成器模式
1. 什么是生成器模式
Builder模式也叫建造者模式或者生成器模式,是由GoF提出的23种设计模式中的一种。Builder模式是一种对象创建型模式之一,用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象。
简单来说就是封装一个复杂对象的构造过程,并允许按照步骤构造。
生成器模式的结构:
- 对象的创建:Builder模式是为对象的创建而设计的模式
- 创建的是一个复合对象:被创建的对象为一个具有复合属性的复合对象
- 关注对象创建的各部分的创建过程:不同的工厂(这里指builder生成器)对产品属性有不同的创建方法
适用场景:
- 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
- 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
- 对象的创建过程独立于创建该对象的类。在建造者模式中通过引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类和客户类中。
- 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
优缺点:
优点:
封装性很好:使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在导演类中对整体而言可以取得比较好的稳定性。
扩展性很好:建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。
有效控制细节风险:由于具体的建造者是独立的,因此可以对建造者过程逐步细化,而不对其他的模块产生任何影响。
将复杂对象的创建过程封装起来
允许对象通过几个步骤来创建,并且可以改变过程(工厂模式只有一个步骤)
只需指定具体生成器就能生成特定对象,隐藏类的内部结构
对象的实现可以被替换
缺点:
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
2. 具体实例
这里举一个具体的例子来介绍生成器模式是怎么使用的.
度假计划生成项目:就是一个公司要推出度假的活动,然后会有具体的安排计划。
度假计划的因素:时间、门票、餐厅、住宿、特殊活动等。
所以我们就像抽象一个度假类,然后每一天去继承和扩展这个类。所以类图如下:
这样一个计划就是一个具体对象,便于扩展。
然后我们基于上面的基础,我们想用户可以自己选择具体是怎么过?选什么样的方式,就是我选3天的度假模式,还是选四天的度假模式,或者是其他种类的。这样的话我们就需要在设计一个抽象类AbsBuilder的类,然后在这个类中实现Vaction,然后用户通过Director就可以自行选择具体是什么样的度假模式,不用管底层的实现,直接使用这个类就可以了。然后要添加新的度假类的时候也不需要修改,符合开闭原则。具体的类图如下:
具体的代码实现:
Vacation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
public class Vacation {private ArrayList<VacationDay> mVacationDayLst;private Date mStDate;private int mDays = 0;private VacationDay mVacationDay;public Vacation(String std) {mVacationDayLst = new ArrayList<VacationDay>();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");try {mStDate = sdf.parse(std);mVacationDay = new VacationDay(mStDate);mVacationDayLst.add(mVacationDay);mDays++;} catch (ParseException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void setStDate(String std) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");try {mStDate = sdf.parse(std);} catch (ParseException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public Date getStDate() {return mStDate;}public void addDay() {mVacationDay = new VacationDay(nextDate(mDays));mVacationDayLst.add(mVacationDay);mDays++;}public boolean setVacationDay(int i) {if ((i > 0) && (i < mVacationDayLst.size())) {mVacationDay = mVacationDayLst.get(i);return true;}mVacationDay = null;return false;}public void setHotel(String mHotels) {mVacationDay.setHotel(mHotels);}public void addTicket(String ticket) {mVacationDay.addTicket(ticket);}public void addEvent(String event) {mVacationDay.addEvent(event);}public void showInfo() {for (int i = 0, len = mVacationDayLst.size(); i < len; i++) {System.out.println("** " + (i + 1) + " day**");System.out.println(mVacationDayLst.get(i).showInfo());}}private Date nextDate(int n) {Calendar cal = Calendar.getInstance();cal.setTime(mStDate);cal.add(Calendar.DATE, n);return cal.getTime();} } |
VacationDay:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public class VacationDay {private Date mDate;private String mHotels;private ArrayList<String> mTickets = null;private ArrayList<String> mEvents = null;public VacationDay(Date date) {mDate = date;mTickets = new ArrayList<String>();mEvents = new ArrayList<String>();}public void setDate(Date date) {mDate = date;}public void setHotel(String mHotels) {this.mHotels = mHotels;}public void addTicket(String ticket) {mTickets.add(ticket);}public void addEvent(String event) {mEvents.add(event);}public String showInfo() {StringBuilder stb = new StringBuilder();stb.append("Date:" + mDate.toString() + "\n");stb.append("Hotel:" + mHotels + "\n");stb.append("Tickets:" + mTickets.toString() + "\n");stb.append("Events" + mEvents.toString() + "\n");return stb.toString();} } |
抽象类AbsBuilder:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public abstract class AbsBuilder {public Vacation mVacation;public AbsBuilder(String std) {mVacation = new Vacation(std);}public abstract void buildvacation();public abstract void buildDay(int i);public abstract void addHotel(String hotel);public abstract void addTicket(String ticket);public abstract void addEvent(String tvent);public Vacation getVacation() {return mVacation;} } |
具体的度假模式(3天):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
public class Builder3d extends AbsBuilder {public Builder3d(String std) {super(std);// TODO Auto-generated constructor stub}@Overridepublic void buildDay(int i) {// TODO Auto-generated method stubmVacation.setVacationDay(i);}@Overridepublic void addHotel(String hotel) {// TODO Auto-generated method stubmVacation.setHotel(hotel);}@Overridepublic void addTicket(String ticket) {// TODO Auto-generated method stubmVacation.addTicket(ticket);}@Overridepublic void addEvent(String event) {// TODO Auto-generated method stubmVacation.addEvent(event);}@Overridepublic void buildvacation() {// TODO Auto-generated method stubaddTicket("Plane Ticket");addEvent("Fly to Destination");addEvent("Supper");addEvent("Dancing");addHotel("Four Seasons");mVacation.addDay();addTicket("Theme Park");addEvent("Bus to Park");addEvent("lunch");addHotel("Four Seasons");mVacation.addDay();addTicket("Plane Ticket");addEvent("City Tour");addEvent("Fly to Home");} } |
4天的模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
public class Builder4d extends AbsBuilder {public Builder4d(String std) {super(std);// TODO Auto-generated constructor stub}@Overridepublic void buildDay(int i) {// TODO Auto-generated method stubmVacation.setVacationDay(i);}@Overridepublic void addHotel(String hotel) {// TODO Auto-generated method stubmVacation.setHotel(hotel);}@Overridepublic void addTicket(String ticket) {// TODO Auto-generated method stubmVacation.addTicket(ticket);}@Overridepublic void addEvent(String event) {// TODO Auto-generated method stubmVacation.addEvent(event);}@Overridepublic void buildvacation() {// TODO Auto-generated method stubaddTicket("Plane Ticket");addEvent("Fly to Destination");addEvent("Supper");addHotel("Hilton");mVacation.addDay();addTicket("Zoo Ticket");addEvent("Bus to Zoo");addEvent("Feed animals");addHotel("Hilton");mVacation.addDay();addTicket("Beach");addEvent("Swimming");addHotel("Home inn");mVacation.addDay();addTicket("Plane Ticket");addEvent("Fly to Home");} } |
Director:在Director中传入Builder,然后构造的时候实现vacation的实例化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class Director {private AbsBuilder builder;public Director(AbsBuilder builder){this.builder=builder;}public void setBuilder(AbsBuilder builder){this.builder=builder;}public void construct(){builder.buildvacation();builder.getVacation().showInfo();} } |
测试类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
public class MainTest {public static void main(String[] args) {Director mDirector = new Director(new Builder4d("2015-12-29"));mDirector.construct();mDirector.setBuilder(new Builder3d("2015-8-30"));mDirector.construct();testself() ;}public static void testself() {BuilderSelf builder = new BuilderSelf("2015-9-29");builder.addTicket("Plane Ticket").addEvent("Fly to Destination").addEvent("Supper").addHotel("Hilton");builder.addDay().addTicket("Zoo Ticket").addEvent("Bus to Zoo").addEvent("Feed animals").addHotel("Home Inn");builder.addDay();builder.addTicket("Beach");builder.addEvent("Swimming");builder.addHotel("Home inn");builder.addDay().addTicket("Plane Ticket").addEvent("Fly to Home");builder.getVacation().showInfo();} } |
3. 生成器模式与抽象工厂的差异
生成器模式和抽象工厂模式在功能上很相似,主要区别:
- 生成器一般用来创建大的复杂的对象
- 生成器模式强调的是一步步创建对象,可以改变步骤来生成不同的对象
- 一般来说生成器模式中对象不直接返回
24种设计模式-生成器模式相关推荐
- 24种设计模式--命令模式【Command Pattern】
今天讲命令模式,这个模式从名字上看就很简单,命令嘛,老大发命令,小兵执行就是了,确实是这个意思,但是更深化了,用模式来描述真实世界的命令情况.正在看这本书的你,我猜测分为两类:已经工作的和没有工作的, ...
- Python七大原则,24种设计模式
七大设计原则: 1.单一职责原则[SINGLE RESPONSIBILITY PRINCIPLE]:一个类负责一项职责. 2.里氏替换原则[LISKOV SUBSTITUTION PRINCIPLE ...
- 24种设计模式(一)
24种设计模式 第1章 简单工厂 第2章 外观模式 第3章 适配器模式 第4章 单例模式 第5章 工厂方法模式 第6章 抽象工厂模式 第7章 生成器模式 第8章 原型模式 第9章 中介者模式 第10章 ...
- 23种设计模式----------代理模式(一)
代理模式也叫委托模式. 代理模式定义:对其他对象提供一种代理从而控制对这个对象的访问.就是,代理类 代理 被代理类,来执行被代理类里的方法. 一般情况下,代理模式化有三个角色. 1,抽象的主题类(或者 ...
- [转自左潇龙的博客]设计模式大杂烩(24种设计模式的总结以及学习设计模式的几点建议)...
原文地址: https://www.cnblogs.com/zuoxiaolong/p/pattern26.html 作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本 ...
- 设计模式大杂烩(24种设计模式的总结及学习设计模式的几点建议)
设计模式大杂烩(24种设计模式的总结及学习设计模式的几点建议)模式分类 & 传送门 & 对比维度说明 设计原则: 设计模式(总纲) 创建型: 单例模式 简单工厂模式 工厂方法模式 抽象 ...
- 24种设计模式之单例模式
24种设计模式之单例模式 一.核心作用: 保证一个类只有一个实例,并且提供一个访问该实例的全局访问点. 二.常见的应用场景: 1.Windows的Task Manager(任务管理器)就是很典型的单 ...
- 23种设计模式——桥接模式
文章目录 23种设计模式--桥接模式 1.桥接模式概述 2.桥接模式结构 3.桥接模式的实现 4.桥接模式的注意事项和细节 23种设计模式--桥接模式 1.桥接模式概述 桥接模式介绍 桥接(Bridg ...
- 23种设计模式-工厂模式
23种设计模式-工厂模式 前言: [我们为什么需要使用工厂模式?] /*** 在使用工厂模式之前,我们要创建 实现了相同接口的对象 都需要直接new(),如下* */@Testpublic void ...
- 23种设计模式——工厂模式
文章目录 23种设计模式--工厂模式 1.工厂模式概述 2.简单工厂模式 2.1.简单工厂模式的优缺点 2.2.简单工厂模式的结构 2.3.简单工厂模式的实现 3.工厂方法模式 3.1.工厂方法模式的 ...
最新文章
- CSDN网友挑选的2007年最有价值文章
- 图像边缘检测技术与理论发展脉络梳理大放送
- 【NGN学习笔记】4 软交换中的协议2—Megaco/H.248
- 白话Elasticsearch27-深度探秘搜索技术之误拼写时的fuzzy模糊搜索技术
- 关于ArrayList转json
- linux运维搭建官网,Linux运维学习之LAMP搭建个人博客网站
- centos7 网卡配置vlan_Centos7单网卡带VLAN多IP配置
- 微信聊天记录做成词云~
- 解决docker中启动Spring Boot微服务注册在Eureka后无法访问的问题
- HTTP权威指南与图解HTTP读书笔记
- 怎么生成a类型的对象 java_用一个 java 程序! 写一个类A, 该类创建的对象可以调用方法f输出英文字母表,然后再编写...
- wpsppt页面卷曲在哪里_2013版ppt怎么制作页面卷曲动画效果
- 一篇文章构建你的 NodeJS 知识体系(W字长文)
- 怎样用css3设计出向上向下的小箭头
- Python数据结构与算法基础|第二期:代码实现——栈的顺序存储与链式存储
- 从0开始学c语言-总结01-c语言的粗略认识和快捷键
- ctfshow_2021月饼杯记录
- [HUBUCTF 2022 新生赛]simple_RE
- 为远控添加功能[1]
- HackTools————3、简易Web端口扫描