java 工厂模式的写法_设计模式-工厂模式

一、概述

什么是工厂模式?

工厂模式(Factory Pattern)是最常见的一种设计模式之一。它主要是提供一种创建对象的最佳方法!

为什么要学习工厂模式?

与通过new来创建对象不同,使用工厂模式创建对象不会对客户端暴露创建逻辑,并且是通过统一个共同的接口指向新创建的对象。同事工厂模式能将创建对象的代码集中在一个对象或者方法中,可以避免代码中的重复,并且更方便维护。面向接口编程,这样的代码更具有弹性,可以应对未来的扩展。

二、认识工厂模式

案例:假设你有一个Pizza店,每天要做出不同口味的Pizza。

假设我们有两种口味Pizza

/*

* 抽象的Pizza类,Pizza制作一般包括准备,烘烤,切块,包装。

*/

public abstract class Pizza{

// Pizza名称

protected String name;

// 面团类型

protected String dough;

// 酱料

protected String sauce;

// 芝士

protected String cheese;

// 蛤蜊

protected String clam;

// 佐料

protected List toppings = new ArrayList();

// 准备

public void prepare() {

System.out.print("准备食材,添加调料:");

for (int i = 0; i < toppings.size(); i++) {

System.out.print(toppings.get(i)+" ");

}

};

// 烘烤

public void bake() {

System.out.println("烘烤20分钟...");

};

// 切块

public void cut() {

System.out.println("切成x块...");

};

// 包装

public void box() {

System.out.println("包装...");

}

// setter 和 getter方法省略

}

芝加哥风味的芝士Pizza

public class ChicagoStyleCheesePizza extends Pizza{

public ChicagoStyleCheesePizza() {

name = "Chicago Style Deep Dish Cheese Pizza";

dough = "Extra Thick Crust Dough";

sauce = "Plum Tomato Sauce";

toppings.add("Shredded Mozzarella Cheese");

}

public void cut() {

System.out.println("Cut the pizza into square slices");

}

}

纽约风味的蔬菜Pizza

public class NyStyleVeggiePizza extends Pizza{

public NyStyleVeggiePizza() {

name = "NY style Sauce and Veggie Pizza";

dough = "Thin Crust Dough";

sauce = "Marinara Sauce";

toppings.add("Grated Reggiano Veggie");

}

}

纽约风味的芝士Pizza

public class NyStyleCheesePizza extends Pizza{

public NyStyleCheesePizza() {

name = "NY style Sauce and Cheese Pizza";

dough = "Thin Crust Dough";

sauce = "Marinara Sauce";

toppings.add("Grated Reggiano Cheese");

}

}

通过new创建对象

// 创建一个纽约风味的芝士Pizza

NyStyleCheesePizza nyPizza = new NyStyleCheesePizza();

当使用new得到一个对象时,确实得到了一个具体类,是针对具体类实现,而不是接口。代码绑定具体类会导致代码脆弱,更缺乏弹性。

简单工厂

public class SimplePizzaFactory {

public Pizza createPizza(String type) {

Pizza pizza = null;

if (type.equals("NyStyleCheesePizza")) {

return new NyStyleChieesePizza();

} else if(type.endsWith("ChicagoStyleCheesePizza")) {

return new ChicagoStyleCheesePizza();

}else {

return null;

}

}

}

// 创建简单工厂对象

SimplePizzaFactory pizzaFactory = new SimplePizzaFactory();

// 创建Pizza对象

NyStyleChieesePizza myPizza = pizzaFactory.createPizza("NYStyleChieesePizza");

简单工厂将对象的创建过程进行了封装,用户不需要知道具体的创建过程,只需要调用工厂类获取对象即可。

这种简单工厂的写法是通过if else来判断对象创建过程的。简单工厂只是把new对象的问题转移到另一个类中在实际使用过程中,违背了 开放-关闭原则,当然有些情况下可以通过反射调用来弥补这种不足。

工厂方法模式

定义:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

01

// 抽象的Pizza工厂

public abstract class PizzaFactory {

public Pizza getPizza(String type) {

Pizza pizza;

pizza = createPizza(type);

pizza.prepare();

pizza.bake();

pizza.cut();

pizza.box();

return pizza;

}

protected abstract Pizza createPizza(String pizza);

}

// 纽约Pizza工厂(芝加哥pizza工厂跟这个类似)

public class NYPizzaFactory extends PizzaFactory {

protected Pizza createPizza(String type) {

if (type.equals("NyStyleChieesePizza")) {

return new NyStyleCheesePizza();

} else if (type.equals("NyStyleVeggiePizza")) {

return new NyStyleVeggiePizza();

}else {

return null;

}

}

}

通过工厂方法创建对象

PizzaFactory pizzaFactory = new NYPizzaFactory();

// 创建一个蔬菜披萨

Pizza pizza = pizzaFactory.createPizza("NyStyleVeggiePizza");

当使用工厂方法创建对象时,是在编写具体工厂类时决定创建的对象时哪一个,选择使用哪个工厂类,自然就决定了十几创建的是哪个对象。尽管只有一个具体工厂,工厂方法还是非常有用的!因为它将对象从“实现”从“使用”中解耦,如果增加对象或者改变对象,工厂是不会受到影响的!

抽象工厂模式

定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

01

抽象原料工厂

// 为了简化, 这里的原料用字符串表示,其实每个原料应该用一个类表示

public interface PizzaIngredientFactory {

public String createDough();

public String createSauce();

public String createChieese();

public String[] createVeggies();

public String createPepperoni();

}

芝士pizza原料工厂

public class CheesePizzaIngredientFactory implements PizzaIngredientFactory {

public String createDough() {

return "薄地壳比萨生面团";

}

public String createSauce() {

return "纽约专用蘸料";

}

public String createChieese() {

return "Reggiano干酪";

}

public String[] createVeggies() {

return new String[]{"洋葱","生菜","香菇"};

}

public String createPepperoni() {

return "意大利辣香肠";

}

}

创建pizza工厂

public class ChinaPizzaFactory extends PizzaFactory {

public Pizza createPizza(String type) {

Pizza pizza = null;

PizzaIngredientFactory ingredientFactory = new ChinaPizzaIngredientFactory();

if(type.equals("cheese")) {

pizza = new CheesePizza(ingredientFactory);

pizza.setName("中国芝士pizza");

}else if (type.equals("clam")) {

pizza = new ClamPizza(ingredientFactory);

pizza.setName("中国蛤蜊pizza");

}

return pizza;

}

}

// 具体的Pizza类

public class ClamPizza extends Pizza {

PizzaIngredientFactory ingredientFactory;

public ClamPizza(PizzaIngredientFactory pizzaIngredientFactory) {

this.ingredientFactory = pizzaIngredientFactory;

}

public void prepare() {

System.out.println("Preparinging" + name);

// 根据pizza本身的特点,从工厂中获取自己需要的原料

dough = ingredientFactory.createDough();

sauce = ingredientFactory.createSauce();

clam = ingredientFactory.creatClam();

}

}

创建一个中国蛤蜊pizza

// 创建一个Pizza工厂

PizzaFactory pizzaFactory = new ChinaPizzaFactory();

Pizza clamPizza = pizzaFactory.createPizza("clam");

抽象工厂模式将'对象' 与 ‘’组成对象或者对象依赖的类‘’解耦。

三、对比与分析

通过new来创建对象是面向具体类编程,扩展性差!

简单工厂把全部的事情都在一个地方处理完了,但是当有新增或者修改的对象类时,很难进行扩展,违反了开闭原则。简单工厂并不能算是工厂模式,而是一种编程习惯,或者是一种方法的封装,并不具备弹性。

工厂方法是创建一个框架,让子类决定如何实现。虽然可能导致类会变多,代码稍微复杂,但是这样做最大的好处是更具有弹性。

工厂模式的好处:将创建对象的代码集中在一个对象或者方法中,可以避免代码中重复的代码,并且方便以后的维护。依赖接口,而不是具体的类。

如何选择?

当需要将对象家族和具体的对象集合结合起来时,可以使用抽象工厂。

当需要将客户代码从需要实例化的具体类中解耦,或者目前还不中知道将来实例化哪些具体类时,可以使用工厂方法。

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

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

相关文章

jackson 序列化_jackson序列化与反序列化的应用实践

作者 | zhouweixin 来源 | urlify.cn/iEbiAz66套java从入门到精通实战课程分享1 相关概念序列化: 把对象转换为字节序列的过程称为对象的序列化反序列化: 把字节序列恢复为对象的过程称为对象的反序列化2 序列化的作用用于把内存中的对象状态保存到一个文件中或者数据库中用于网…

java mqtt客户端_基于 t-io 实现一个 mqtt5 协议之 mica-mqtt

一、简介 MQTT 全称为 Message Queuing Telemetry Transport&#xff08;消息队列遥测传输&#xff09;是一种基于发布/订阅范式的“轻量级”消息协议&#xff0c;由 IBM 发布。目前使用比较广泛的就是 mqtt 3.1.1&#xff08;2014年制定&#xff09;&#xff0c;mqtt 5.0&…

java自我介绍_JAVA面试技巧之自我介绍

【如何进行自我介绍】自我介绍这个问题&#xff0c;不用多说了&#xff0c;面试必定会问&#xff01;如果想要在自我介绍的时候就能够打动面试官&#xff0c;吸引面试官对我们的兴趣&#xff0c;那么像我们这种接受过Java培训的程序员的自我介绍当然不能和应届生或者其他非技术…

java excel 操作 poi_Java使用apache poi进行excel相关操作

一.基本介绍1.1、Apache POI介绍Apache POI是一个可以进行微软的文档进行开源库&#xff0c;可以操作的文档类型包括word、ppt、excel、visio、outlook....本文主要针对Apache POI对excel的操作进行介绍&#xff0c;主要包括如何创建一个excel、录入数据、读取excel数据的方式。…

程序解析excel中的图片_产品日志丨支持导入Excel中的图片amp;批量修改后期实体字段...

本次安捷秀又迎来了一个大版本更新&#xff0c;除了大家呼声很高的「实体模块导入 Excel 」外&#xff0c;还有「批量编辑实体」&#xff0c;「支持右击修改」以及针对海外用户的「全页面支持英文」等功能的新增与优化&#xff0c;一起来看看吧。导入功能优化AGILESHOT&#xf…

java不同垃圾回收器_细述 Java垃圾回收机制→Types of Java Garbage Collectors

本文非原创&#xff0c;翻译自Types of Java Garbage Collectors在Java中为对象分配和释放内存空间都是由垃圾回收线程自动执行完成的。和C语言不一样的是Java程序员不需要手动写垃圾回收相关的代码。这是使得Java如此流行&#xff0c;同时也是Java能帮助程序员写出更好的Java应…

js修改地址栏url_不同寻常的地址栏过渡

前几天&#xff0c;我在推特上看到这样一张图。原来地址栏还能这么玩&#xff0c;瞬间就觉得自己弱爆了。然后我决定去实现一下这个效果&#xff0c;然后做成一个库。画了一个晚上&#xff0c;终于做好了。这是最后的成果。这个库使用非常的简单。你只需要&#xff0c;yarn add…

kaggle数据集_ArXiv170万篇论文数据集上线Kaggle!

大数据文摘出品学术圈的朋友对ArXiv肯定都不陌生。在将近30年的时间里&#xff0c;ArXiv通过公开访问学术文章为公众和研究社区提供了一个更高效的学术成果沟通平台&#xff0c;从物理学到计算机科学的许多子学科&#xff0c;以及介于两者之间的所有内容&#xff0c;包括数学&a…

万能驱动xp离线版_教你用SC封装软件来封装XP系统

今天我们来讲解一下如何用SC软件来封装XP系统。今天的讲解只演示基本的SC封装软件&#xff0c;具体的封装前的准备工具&#xff0c;我们不进行讲解&#xff0c;当然前期的准备工作也是有很多&#xff0c;首先我们先要安装虚拟机软件&#xff0c;并在虚拟机上面安装好原版的XP系…

java dispo lock_java实现文件上传和下载(1)

原理&#xff1a; 使用html 的 标签&#xff0c;提交form 的几个属性必须为&#xff1a; methodpost encTypemultipart/form-data;组件:smartUpload或者commons fileuploadsmartUpload代码实现1。文件预览function showImage(obj){var strobj.value;$("#id").html(&q…

剪板机自动上下料_机器人联轴器,用于机器人自动化上下料

关注点击蓝字&#xff0c;关注我吧纤薄型机器人联轴器&#xff0c;可搬运重量范围从 1kg 至 1,000kg&#xff0c;用于高效机器人自动化机床上下料&#xff0c;多年来受到广泛认可。紧凑型微型联轴器适合于最近迅速发展的小型机器人应用领域。无人操作时工艺可靠性高模块的特殊混…

java 格式化 布尔型_Java基础篇(1)-格式化

本文目录&#xff1a;十进制数字格式化——DecimalFormat数字格式化基类——NumberFormat字符串格式化类——String.format()Linux输出格式化——printf1. 十进制数字格式化(DecimalFormat)decimal是对数字进行格式化&#xff0c;比如取2位小数&#xff0c;这是最常见的。Java提…

一旦有辞职念头就干不长了吗_每天都有辞职不想上班的冲动,你有吗?

我从大学毕业到今天&#xff0c;工作的时间将近10年了。直到现在&#xff0c;我还经常有辞职的想法。我觉得现在职场真的不好混&#xff0c;不如意的事情十之八九&#xff0c;有了辞职冲动是非常正常的&#xff0c;不必一上来就刻意的否定&#xff0c;或者克制。依照我的职场经…

mysql 序号_脚本搭建Nginx、Redis、MySql、Maven

当你面对一个全新的Linux系统时&#xff0c;是如何部署搭建项目环境呢&#xff1f;是否是一个一个软件安装呢&#xff1f;小编在往期文章中介绍了相关软件的安装方法&#xff0c;但是你是否发现不同的软件安装下来是否会出现问题呢&#xff1f;今天就教大家如何使用脚本一键安装…

mysql数据库子查询的使用_MySQL数据库使用子查询方式更新数据优化及思考

【环境介绍】云数据库MySQL 5.7【背景描述】业务需要&#xff1a;需要对16370077的表数据进行更新部分数据操作UPDATE P_MOXXXX_REXXXX SET FISAVAILABLE 1 WHERE FREG_ID IN (SELECT FREG_ID FROM P_MOXXXX_REXXXX_UPDATE_TEMP);【按照正常流程更新数据操作】使用archery的SQ…

业务中台建设与应用_容易网业务中台建设,助力企业数字化转型

“中台”这个概念自去年流行以来&#xff0c;至今仍然搅动着市场。期间&#xff0c;既有阿里、腾讯、百度、字节跳动、美团、滴滴等等头部互联网企业刮起的转型风&#xff0c;也有茅台延后中台签约、服装品牌CIO被开除等风波。尽管存在争议&#xff0c;但这不影响越来越多的企业…

java由大到小输出整数xvz_【视频+图文】Java经典基础练习题(三):输入3个整数,并将其由小到大输出...

java经典实例书店书畅想畅销书109.6元包邮(需用券)去购买 >目录https://www.cnblogs.com/Qpgshare/p/12588923.html一、视频讲解https://www.cnblogs.com/Qpgshare/p/12588923.html二、思路分析https://www.cnblogs.com/Qpgshare/p/12588923.html总结&#xff1a;https://ww…

压力测试过负载均衡_性能测试的方法有哪些?

压力测试&#xff1a;压力测试的关键字就是“极端”。通过对系统的极端加压&#xff0c;从而观察系统的所表现出来性能问题。再对此性能问题进行分析&#xff0c;从而达到系统优化的目的。所以压力测试就是一定要让系统出问题&#xff0c;如果系统没有出问题&#xff0c;那么压…

java比ios慢_Android为什么比iOS慢

有些人会觉Android应用没有iOS应用使用得流畅&#xff0c;我觉得主要原因有以下几点&#xff1a;第一&#xff0c;因为Android平台相较于iOS起步晚&#xff0c;平台不成熟&#xff0c;初期的开发者水平也有限&#xff0c;没有很关注性能优化&#xff0c;只是想做出可用的应用&a…

output怎么用_如何用 C++ 写一个可编程软件渲染器?

今天你想用最新的 D3D12 画一个三角形&#xff0c;少说也要上千行代码了&#xff0c;对于初学者来讲&#xff0c;这个门槛是非常高的&#xff0c;太多干扰了&#xff0c;而一千多行代码&#xff0c;已经足够你重头实现一个简易版 D3D 了&#xff0c;为什么不呢&#xff1f;比起…