Java设计模式 | 简单工厂模式

在这里插入图片描述

概述

需求

设计一个咖啡店点餐系统
设计一个咖啡类(Coffee);并定义其两个子类(美式咖啡AmericanCoffee和拿铁咖啡LatteCoffee);再设计一个咖啡店类(CoffeeStore),其具备点咖啡的功能。

类图

image.png

咖啡类
public abstract class Coffee {// 获取咖啡名public abstract String getName();// 加糖public void addSugar(){System.out.println("加糖");}// 加奶public void addMilk(){System.out.println("加奶");}
}

美式咖啡类
public class AmericanCoffee extends Coffee {@Overridepublic String getName() {return "美式咖啡";}
}

拿铁咖啡类
public class LatteCoffee extends Coffee {@Overridepublic String getName() {return "拿铁咖啡";}
}

咖啡店类
public class CoffeeStore {public Coffee orderCoffee(String type) {// 根据类型创建咖啡实例Coffee coffee = null;if("Latte".equals(type)) {coffee = new LatteCoffee();}else if("Americano".equals(type)) {coffee = new AmericanCoffee();}else {System.out.println("Sorry, we don't have this kind of coffee.");}// 加糖和奶coffee.addSugar();coffee.addMilk();return coffee;}
}
测试
public class Client {public static void main(String[] args) {// 1 创建咖啡店类CoffeeStore coffeeStore = new CoffeeStore();// 2 点咖啡Coffee coffee = coffeeStore.orderCoffee("Latte");System.out.println(coffee.getName());}
}

在Java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new,就会对该对象耦合严重,假如需要更换对象,所有new的地方都需要修改一遍,这显然违背了开闭原则。如果使用工厂来生产对象,就只需要和工厂打交道就好了,彻底和对象解耦,如果需要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的。所以说,工厂模式的最大优点就是:解耦

三种工厂:

  • 简单工厂模式(不属于GOF的23种经典设计模式)
  • 工厂方法模式
  • 抽象工厂模式

简单工厂模式

简单工厂不是一种设计模式,反而比较像是一种编程习惯。

结构

简单工厂包含以下角色:

  • 抽象产品:定义了产品的规范,描述了产品的主要特征和功能(通用行为)
  • 具体产品:实现或继承抽象产品(接口/抽象类)的子类
  • 具体工厂:提供了创建产品的方法,调用者通过该方法来获取产品(根据传递的不同参数来创建不同的产品示例)
实现

image.png
咖啡类:

public abstract class Coffee {// 获取咖啡名public abstract String getName();// 加糖public void addSugar(){System.out.println("加糖");}// 加奶public void addMilk(){System.out.println("加奶");}
}

美式咖啡类:

public class AmericanCoffee extends Coffee {@Overridepublic String getName() {return "美式咖啡";}
}

拿铁咖啡类:

public class LatteCoffee extends Coffee {@Overridepublic String getName() {return "拿铁咖啡";}
}

简单咖啡工厂类:

public class SimpleCoffeeFactory {public Coffee createCoffee(String type) {// 根据类型创建咖啡实例Coffee coffee = null;if("Latte".equals(type)) {coffee = new LatteCoffee();}else if("Americano".equals(type)) {coffee = new AmericanCoffee();}else {System.out.println("Sorry, we don't have this kind of coffee.");}return coffee;}
}

咖啡店类:

public class CoffeeStore {public Coffee orderCoffee(String type) {// 实例化工厂SimpleCoffeeFactory simpleCoffeeFactory = new SimpleCoffeeFactory();// 调用生产咖啡的方法Coffee coffee = simpleCoffeeFactory.createCoffee(type);// 加糖和奶coffee.addSugar();coffee.addMilk();return coffee;}
}

测试:

public class Cilent {public static void main(String[] args) {// 创建咖啡店类对象CoffeeStore coffeeStore = new CoffeeStore();// 点咖啡Coffee coffee = coffeeStore.orderCoffee("Latte");System.out.println(coffee.getName());}
}

总结

工厂(factory)处理创建对象的细节,一旦有了SimpleCoffeeFactory,CoffeeStore类中的orderCoffee()就变成此对象的客户,后期如果需要Coffee对象直接从工厂中获取即可。这样就解除了CoffeeStore和Coffee实现类的耦合,同时又产生了新的耦合,CoffeeStore和SimpleCoffeeFactory的耦合,工厂对象和商品对象的耦合。
后期如果需要增加新咖啡,势必需要修改SimpleCoffeeFactory的代码,违反了开闭原则。工厂的客户端可能有很多,如创建美团外卖等,这样只需要修改工厂类的代码,省去了其他的操作。

简单工厂简化了客户端操作,客户端可以调用工厂方法来获取具体的产品,而无需直接与具体产品类交互,降低了耦合,但是有一个很大的问题就是不够灵活,如果需要添加新产品,就需要修改工厂类的代码。

优点:

  • 封装了创建对象的过程,可以通过参数直接获取对象
  • 把对象的创建和业务逻辑层分开,避免了修改客户端的代码,如果要实现新产品直接修改工厂类,不需要在原代码中修改,降低客户代码修改的可能性,更容易扩展

缺点:

  • 增加新产品时需要修改工厂类的代码,违背了开闭原则

扩展(静态工厂)

在实际开发中,一部分开发人员将工厂类中创建对象的功能定义成静态的,这就是静态工厂模式,也不属于23种设计模式,是一种编程习惯。
好处就是客户端可以不用实例化工厂对象,直接调用即可。

public class SimpleCoffeeFactory {public static Coffee createCoffee(String type) {// 根据类型创建咖啡实例Coffee coffee = null;if("Latte".equals(type)) {coffee = new LatteCoffee();}else if("Americano".equals(type)) {coffee = new AmericanCoffee();}else {System.out.println("Sorry, we don't have this kind of coffee.");}return coffee;}
}

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

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

相关文章

12350安全生产举报热线系统解决方案

一、建设背景 1. 安全生产的重要性 在当今社会,安全生产是企业和社会发展中至关重要的一环。随着工业化的推进和技术的不断创新,各种生产活动中潜在的安全隐患也随之增加。为了及时发现和解决这些问题,各省市纷纷设立了安全生产举报热线。在…

Node.js常用命令:了解Node.js的核心命令和用法

学习目标: 理解Node.js和npm的概念及其在开发中的作用;掌握Node.js的核心命令,包括node、npm、npx等;学会使用node命令来执行JavaScript文件和模块;熟悉npm命令,包括安装、更新、卸载依赖包等操作&#xf…

openssl3.2 - exp - aes-128-cbc

文章目录 openssl3.2 - exp - aes-128-cbc概述笔记openssl 命令行实现简单直白的实现简单直白的实现 - 测试效果简单直白的实现 - 测试工程 周全灵活的实现周全灵活的实现 - 测试效果周全灵活的实现 - 测试工程 END openssl3.2 - exp - aes-128-cbc 概述 想将工程中用到的字符…

【Ubuntu】常用命令

一般操作 pwd(present working directory) 显示当前的工作目录/路径。 cd (change directory) 改变目录,用于输入需要前往的路径/目录。 有一些特殊命令也很常用 : 解释 前往同一级的另一个目录 cd ../directory name cd .. 表示进入上…

技术周刊 116 期:Visual Copilot、INP、Kimi 支持 200 万字上下文、Grok 开源、Figure 01、Open Sora 开源

美味值:🌟🌟🌟🌟🌟 口味:话梅排骨 食堂技术周刊仓库地址:https://github.com/Geekhyt/weekly 大家好,我是童欧巴。欢迎来到前端食堂技术周刊,我们先来看下…

STP环路避免实验(华为)

思科设备参考:STP环路避免实验(思科) 一,技术简介 Spanning Tree Protocol(STP),即生成树协议,是一种数据链路层协议。主要作用是防止二层环路,并自适应网络变化和故障…

unity学习(62)——emptyObject+昵称+血条

1.地图比较麻烦,先最后回头再做,地图是锦上添花的东西。 2.MapHandler中的使用技巧: 2.1.继承必须有,要不脚本绑不到相机上 2.2当场景被调用时触发函数OnLevelWasLoaded,这个和Start一样属于一个机制函数。 3.自己做…

长安链Docker Java智能合约引擎的架构、应用与规划

#功能发布 长安链3.0正式版发布了多个重点功能,包括共识算法切换、支持java智能合约引擎、支持后量子密码、web3生态兼容等。我们接下来为大家详细介绍新功能的设计、应用与规划。 在《2022年度长安链开源社区开发者调研报告》中,对Java合约语言支持是开…

分布式幂等性解决方案

分布式幂等性如何设计: 在高并发场景的架构里,幂等性是必须得保证的。比如说支付功能,用户发起支付,如果后台没有做幂等校验,刚好用户手抖多点了几下,于是后台就可能多次受到同一个订单请求,不…

51单片机—直流电机

1.元件介绍 2.驱动电路 3.电机调速 一般会保证一个周期的时间是一样的 应用&#xff1a; 1.LED呼吸灯 #include <REGX52.H>sbit LEDP2^0;void Delay(unsigned int t) {while(t--); } void main() {unsigned char Time,i;while(1){for(Time0;Time<100;Time){for(i0;…

【前端寻宝之路】学习和总结HTML的标签属性

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不…

Linux-Arm环境下配置编译qt-everywhere及交叉编译环境

前言 最近在搞交叉编译的事&#xff0c;手上拿了个同事的香橙派玩交叉编译&#xff0c;现在来到了第一步&#xff0c;就是先在arm上配置qt的开发环境。当然了Qt没有直接提供qt on arm&#xff0c;而是需要自行在arm环境下编译一个qt环境出来&#xff0c;所以这里需要使用到qt提…

【Linux】vim详细介绍(四)

文章目录 什么是 vimvim的主要功能&#xff1a;vim的三种模式.viminfo和.vimrc文件 什么是 vim 点击跳转至官网了解更多 Vim是一款功能强大的文本编辑器&#xff0c;适用于各种编程和文本处理任务&#xff0c;最初由Bram Moolenaar开发于1991年。它是Vi编辑器的增强版&#xf…

项目当中 签到功能 +多级缓存+介绍一下点赞功能

签到是怎么做的&#xff1f; 刚开始想用数据库做来着&#xff0c;后来发现用数据库数据量太大&#xff0c;就找解决方案&#xff0c;想到了用bitMap 位图。 bitMap 位图是什么 &#xff1f; 我们采用的是radis 里的bitMap结构 他本质是字符串 最大512mb 是使用01 来存储…

GitHub Copilot+ESP开发实战-串口

上篇文章讲了GitHub Copilot在应用中可能遇到的问题&#xff0c;接下来小启就简单介绍下GitHub Copilot在ESP32开发中C语言实现串口功能&#xff0c;感兴趣的可以看看。 一、向Copilot提问&#xff1a; 1. ESP32用C语言实现串口初始化&#xff1b; 2.配置uart为1&#xff0c…

【Thread 线程】线程的方法与状态

SueWakeup 个人中心&#xff1a;SueWakeup 系列专栏&#xff1a;学习Java 个性签名&#xff1a;保留赤子之心也许是种幸运吧 本文封面由 凯楠&#x1f4f7; 友情赞助播出&#xff01; 目录 一个线程的生命周期 线程终止的原因 线程的方法 Thread 类的静态方法 1. 设置线程…

59、服务攻防——中间件安全CVE复现IISApacheTomcatNginx

文章目录 中间件——IIS漏洞中间件——Nginx漏洞中间件——Apache中间件——Tomcat 中间件&#xff1a;IIS、Apache、Nginx、Tomcat、Docker、Weblogic、JBoss、WebSphere、Jenkinsphp框架&#xff1a;Laravel、Thinkphppythonl框架&#xff1a;Flaskjs框架&#xff1a;jQueryj…

为什么要减少Http的请求以及如何减少Http请求

为什么要减少Http的请求 减少 HTTP 请求的数量是优化网页性能的一个重要策略&#xff0c;原因有以下几点&#xff1a; 1.延迟&#xff1a;每个 HTTP 请求都会有一定的网络延迟。即使数据量很小&#xff0c;请求和响应的往返时间也可能相当长&#xff0c;特别是在网络条件不好…

王道c语言-链表分为两半,逆置后一半,与前一半轮流合并

王道c语言-链表分为两半&#xff0c;逆置后一半&#xff0c;与前一半轮流合并 设线性表 L ( a 1 , a 2 , a 3 , ⋯ , a n − 2 , a n − 1 , a n ) L(a_1,a2,a3,\cdots,a_{n-2},a_{n-1},a_{n}) L(a1​,a2,a3,⋯,an−2​,an−1​,an​) 采用带头结点的单链表保存&#xff0c;…

【Unity】从0到1的横版2d制作笔记-DAY1

写在前面&#xff1a; 感谢旻子提供的Unity2d课程捏&#xff0c;红豆泥阿里嘎多 创建项目 测试Visual Studio的使用 右键选择【create】&#xff0c;右键创建C# Script&#xff0c;待文件创建完毕后双击查看能否正确跳转。 正确跳转的结果是能看见代码中注释标注有&#xff1a;…