Java常用设计模式————建造者模式

引言

建造者模式(Builder Pattern)使用多个简单对象一步一步构建成一个复杂的对象。这种类型的设计模式属于建造型模式,它提供了一种创建对象的最佳方式。

一个Builder会一步步构建最终的对象。该Builder类是独立于其他对象的。

实现概要

建造者模式的实现并没有一个特别经典的套路,原因是在多数情况下复杂对象的构建往往千奇百怪。但为了更好的理解建造者模式使用的场景,我们假设如下的功能需要:

因为建造者模式就是为了构建复杂对象,为了更加贴近这一点,以午餐(Meal)作为最终要被构建的对象,我们假设:午餐中分为食物(Item)包装(Packing)—>食物包含汉堡(Burger)冷饮(ColdDrink)两种;汉堡鸡肉汉堡(ChickenBurger)蔬菜汉堡(VegBurger)之分;冷饮可口可乐(Coke)百事可乐(Pepsi)之分;包装又分为瓶装(Bottle)袋装(Wrapper)两种。

如果你看不懂上面的描述,或者已经准备关闭浏览器去做眼睛保健操,那么下面的结构图可能对你有所帮助:

实现过程

一、创建基础接口

创建食物接口及具体实现类,创建包装接口及具体包装类:

public interface Item {/** 食物名称*/String name();/** 包装*/Packing packing();/** 总价*/float price();
}
public abstract class Burger implements Item {@Overridepublic Packing packing() {return new Wrapper();}
}
public class ChickenBurger extends Burger {@Overridepublic String name() {return "Chicken Burger";}@Overridepublic float price() {return 50.5f;}
}
public class VegBurger extends Burger {@Overridepublic String name() {return "Veg Burger";}@Overridepublic float price() {return 25.0f;}
}
public abstract class ColdDrink implements Item {@Overridepublic Packing packing() {return new Bottle();}
}
public class Coke extends ColdDrink {@Overridepublic String name() {return "Coke";}@Overridepublic float price() {return 30.0f;}
}
public class Pepsi extends ColdDrink {@Overridepublic String name() {return "Pepsi";}@Overridepublic float price() {return 35.0f;}
}
public interface Packing {String pack();
}
public class Bottle implements Packing {@Overridepublic String pack() {return "Bottle";}
}
public class Wrapper implements Packing {@Overridepublic String pack() {return "Wrapper";}
}

二、创建目标类型

此例中,目标类型即午餐类(Meal)

public class Meal {private List<Item> items = new ArrayList<Item>();public Meal addAll(List<? extends Item> items) {this.items.addAll(items);return this;}public Double getSum() {return this.items.stream().collect(Collectors.summarizingDouble(Item::price)).getSum();}public Double getAverage() {return this.items.stream().collect(Collectors.summarizingDouble(Item::price)).getAverage();}public void showItems() {this.items.forEach(item -> {System.out.print("Item : " + item.name());System.out.print(", Packing : " + item.packing().pack());System.out.println(", Price : " + item.price());});}
}

三、创建建造者类

public class MealBuilder {public Meal prepareMeal(Item... items) {return new Meal().addAll(Arrays.asList(items));}
}

四、测试

public class BuilderPatternDemo {public static void main(String[] args) {MealBuilder mealBuilder = new MealBuilder();Meal vegMeal = mealBuilder.prepareMeal(new VegBurger(), new Coke());System.out.println("Veg Meal");vegMeal.showItems();System.out.println("Total Cost: " + vegMeal.getSum());Meal nonVegMeal = mealBuilder.prepareMeal(new ChickenBurger(), new Pepsi());System.out.println("\n\nNon-Veg Meal");nonVegMeal.showItems();System.out.println("Total Cost: " + nonVegMeal.getSum());}
}

执行结果:

总结

意图:建造者模式的用意就是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示,例如本例中相同的创建午餐的方式,但使用不同的基础对象,最终得出不一样的套餐。

使用场景:一些基础部件不会变,而其组合经常变化的时候。主要解决软件系统中,有时候会面临“一个复杂对象”的创建工作,其通常由多个子对象用一定的算法构成。由于需求的变化,这个复杂对象的各个部件经常面临着剧烈的变化,但将它们组合在一起的算法相对稳定。

优点:建造者独立,易扩展;便于控制细节风险。

缺点:产品必须有共同点,范围有限制;内部变化复杂,会有很多建造类。

鸣谢

《建造者模式》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/558924.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用动态代理解决网站字符集编码问题:(之前通过拦截器)

使用动态代理解决网站字符集编码问题&#xff1a;&#xff08;之前通过拦截器&#xff09; 设计模式&#xff1a; 在软件开发的过程中&#xff0c;遇到相识的问题&#xff0c;将问题的解决方式抽象为模型&#xff08;套路&#xff09; 单例模式&#xff08;静态代码只会执行一…

Java 多线程 —— AQS 原理

引言 使用Condition实现生产者-消费者模型&#xff0c;并与wait和notify实现的效果相对比。 wait/notify模拟生产者-消费者 面试题&#xff1a;写一个固定容量同步容器&#xff0c;拥有put和get方法&#xff0c;以及getCount方法能够支持2个生产线程以及10个消费者线程的阻塞…

设计模式---简单工厂设计模式

先定义一个抽象类Animal&#xff1a; 定义两个动物类继承这个类&#xff1a; 定义一个专门生产动物的工程类&#xff1a; 最后定义一个测试类&#xff1a; 按照这个动物工厂类&#xff0c;你会发现&#xff0c;如果动物一多的话&#xff0c;就需要写很多重复的方法&#xff0c;…

Java 多线程 —— ThreadLocal

一、引言 ThreadLocal是Java帮助实现线程封闭性的典型手段。 作用&#xff1a;提供线程内的局部变量&#xff0c;这种变量在线程的生命周期内起作用&#xff0c;减少同一个线程内多个函数或组件之间一些公共变量的传递复杂度。同时也用来维护线程中的变量不被其他线程干扰。 …

Java8————方法引用

译者注&#xff1a;本篇博客翻译自Oracle官方教程《Method References》。作为Java 8 新特性Lambda表达式的引申概念&#xff0c;博主依然采用官方文档的方式来学习这一重要的概念。希望对各位同道有所帮助。 方法引用 使用Lambda表达式创建匿名方法。但是&#xff0c;有时候…

设计模式---适配器设计模式

设计模式---适配器设计模式 什么事适配器&#xff1a; 1. 在使用监听的时候&#xff0c;需要定义一个类事件监听器接口 2. 通常接口中有多个方法&#xff0c;而程序中不一定所有的方法都用到&#xff0c;但又必须重写&#xff0c;很繁琐 3. 适配器简化了这些操作&#xff0c…

Java并发编程实战————售票问题

引言 现有一个需求如下&#xff1a; 有10000张火车票&#xff0c;每张票都有一个编号&#xff0c;同时有10个窗口对外售票&#xff0c;如何确保车票的正常售卖&#xff1f; 程序一&#xff1a;使用List 问题的解决办法都是从我们最最熟悉的角度思考。程序一&#xff0c;我们…

多线程相关知识

多线程相关知识 两个线程进行通信&#xff1a;通过等待&#xff08;wait&#xff09;唤醒&#xff08;notify&#xff09;机制 三个或三个以上线程进行通信&#xff1a;通过notifyAll&#xff08;&#xff09;方法 /* * 1. 在同步代码块中&#xff0c;用哪个对象锁&#xff0c…

Eclipse集成PyDev5.2.0开发插件

引言 在进行Python学习的时候&#xff0c;希望不使用IDLE进行开发&#xff0c;但是其他的IDE如PyCharm可能需要一段短暂时间的上手&#xff0c;因为开发过Java&#xff0c;所以使用能够集成到Eclipse上的PyDev插件进行开发应该会好一些。 但是在安装PyDev的时候发生了一些问题…

PostMan 四种常见的 POST 提交数据方式

HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 这几种。其中 POST 一般用来向服务端提交数据&#xff0c;本文主要讨论 POST 提交数据的几种方式。 协议规定 POST 提交的数据必须放在消息主体&#xff08;entity-body&#xff0…

Java并发编程实战————对象的组合

引言 对象的组合&#xff0c;是《Java Concurrency in Practice》中第四章引入的课题。这并不是一个并发的概念。 为了可以将现有的线程安全组件组合为更大规模的组件或程序&#xff0c;而不是每次内存访问都进行分析以确保程序是线程安全的。这一章将介绍一些组合模式&#…

史上最真实行业鄙视链

本文转载自菜鸟教程的微信公众号&#xff0c;原文链接&#xff1a;https://mp.weixin.qq.com/s/d9cdtq8y4Msq-_ZNof-iuw 引言 作为程序员的一份子&#xff0c;掌握好各个生态系统中的鄙视链&#xff0c;可以写出更加符合改变世界要求的代码。掌握了鄙视链&#xff0c;就掌握了…

如何快速理清大型项目业务逻辑

引言 本篇文章为了探讨如何快速上手一个大型项目。针对经验尚浅需要快速接手一个项目的开发人员。 当他们拿到一个大型程序后&#xff0c;他们便开始一句一句的阅读分析&#xff0c;夜以继日&#xff0c;悬梁刺股。可结果依然不理想&#xff0c;往往进入以下状态&#xff1a;…

权限验证框架Shiro

权限验证框架Shiro&#xff1a; Shiro简介 什么是Shiro&#xff1a; shiro是一个强大易用的Java安全框架&#xff0c;提供了认证&#xff0c;授权&#xff0c;加密&#xff0c;回话管理等功能&#xff1b; 认证&#xff08;Authentication&#xff09;&#xff1a;用户身份识别…

Linux——less指令常用操作

引言 对于生产环境、测试环境中的日志文件&#xff0c;我们可以通过less指令来进行查看并通过关键字进行查找。less命令的含义是&#xff1a;分屏查看文件内容。 它要比more命令更加强大&#xff0c;less在显示文件内容时&#xff0c;并不是一次将整个文件加载之后才显示&…

Mybatis从入门到精通上篇

Mybatis从入门到精通上篇&#xff1a; 学习过的持久层框架&#xff1a;DBUtils , Hibernate Mybatis就是类似于hibernate的orm持久层框架。 Mybatis介绍&#xff1a; Mybatis是面向sql的持久层框架&#xff0c;他封装了jdbc访问数据库的过程&#xff0c;我们开发&#xff0c;只…

Eclipse使用————Working Set工作集

引言 经常看到在设置项目的时候&#xff0c;如导入项目&#xff0c;新建项目等看到对话框的下方有一个“add to working set”复选框&#xff0c;为了弄清这个working set&#xff0c;我们就来好好了解一下Eclipse 的working set功能。 Working Set&#xff1f; Eclipse中通…

Mybatis从入门到精通下篇

Mybatis从入门到精通下篇&#xff1a; 输入类型&#xff1a; 输出类型&#xff1a; ResultMap&#xff1a; 动态sql&#xff1a; if标签&#xff1a; where标签&#xff1a; sql片段&#xff1a; foreach标签&#xff1a; 关联查询&#xff1a; 以订单作为主体&#xff1a; 一…

爱上进制转换练习

引言 对于可能接触到通讯行业或是物联网的开发工作者&#xff0c;一般会面对十进制、二进制、十六进制的转换工作&#xff0c;不仅仅是体现在代码上&#xff0c;有时候也需要用肉眼来进行快速的转化&#xff0c;以获取协议指令中的信息。 今天通过简单的整理&#xff0c;特此…

Sprint Boot————@Qualifier、@Primary

引言 使用Autowired自动注入时&#xff1a; 如果注入的接口有多个实现类&#xff0c;如下所示&#xff1a; 那么如果不指定具体是哪个实现类的Bean&#xff0c;在Spring Boot启动时就会发生异常&#xff08;下图请点击查看&#xff09;&#xff1a; 异常的描述信息非常简单&am…