Head First Design Patterns -工厂模式

什么是工厂模式

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

为什么要有工厂模式

书中以pizza店制作pizza为例子,假设不用工厂模式,在制作pizza阶段我们需要这样去实例化类:

Pizza orderPizza(String type) {Pizza pizza;// 基于pizza的类型,实例化具体的类,这里的每个pizza都需要实现Pizza接口if (type.equals("cheess")) {pizza = new CheesePizza();} else if (type.equals("greek")) {pizza = new GreekPizza();}// pizza的前期准备pizza.prepare();pizza.bake();return pizza;
}

上述代码不符合开闭原则,一旦pizza店改变pizza的供应,则需要修改上述代码

简单工厂模式

简单工厂模式并不是一种设计模式,而是一种编程习惯,定义一个工厂类,这个类封装所有披萨的对象创建,pizza店客户端中不会进行实例化

代码如下:

// 简单工厂代码
public Pizza SimplePizzaFactory {public Pizza createPizza(String type) {Pizza pizza = null;if (type.equals("cheess")) {pizza = new CheesePizza();} else if (type.equals("greek")) {pizza = new GreekPizza();}}
}// pizza店客户端代码
public class PizzaStore {SimplePizzaFactory factory;public PizzaStore(SimplePizzaFactory factory) {this.factory = factory;}public Pizza orderPizza(String type) {Pizza pizza;pizza = factory.createPizza(type);// pizza的前期准备pizza.prepare();pizza.bake();return pizza;}
}

简单工厂模式的类图:
在这里插入图片描述

简单工厂模式的优点:

  • 将变化的部分抽离出来独立形成工厂,避免在客户端直接创建

简单工厂模式的缺点:

  • 简单工厂只是提供了封装对象创建的一种方式,但没有提供工厂方法的弹性,因为它没有办法改变正在创建的产品。

工厂模式

如果pizza店引入了加盟商,加盟商对于pizza需要有一些自己的定制化需求,而上面的简单工厂模式,则不符合这种需求,需要引入工厂模式。

具体代码:

1、定义pizza店接口

public abstract class PizzaStore {public Pizza orderPizza(String type) {Pizza pizza;pizza = createPizza(type);pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;}protected abstract Pizza createPizza(String type); // 交给子类进行实例化
}

2、 抽象pizza的制作流程

public abstract class Pizza {String name;String dough;void prepare() {System.out.println("prepare finish");};void bake() {System.out.println("bake finish");};void cut() {System.out.println("cut finish");};void box() {System.out.println("box finish");};public String getName() {return name;};
}

3、定义加盟商的定制化需求

public class NYPizzaStore extends PizzaStore{@Overridepublic Pizza createPizza(String item) {if (item.equals("cheese")) {return new NYStyleCheesePizza();}else return null;}
}

4、定义加盟商所使用的pizza材料

public class NYStyleCheesePizza extends Pizza{public NYStyleCheesePizza() {String name = "NY Style pizza";String dough = "thin crust dough";String sauce = "Marinara Sauce";}
}

5、main函数执行

public class Main {public static void main(String[] args) {PizzaStore nyStore = new NYPizzaStore();Pizza pizza = nyStore.orderPizza("cheese");}}

执行结果:

prepare finish
bake finish
cut finish
box finish

工厂模式的类图:
在这里插入图片描述

工厂模式中引入的设计原则:

  • 依赖倒置原则:依赖抽象,而不应该依赖具体类

遵循依赖倒置设计原则的指南:

  • 变量不应该持有到具体类的引用
  • 类不应该派生自具体类
  • 方法不应该覆盖任何基类的已实现方法
    (以上指南并不是铁律,要看具体的场景来遵守)

抽象工厂模式

抽象工厂模式提供一个接口来创建相关或依赖对象的家族,而并不需要指定具体的类

比较工厂方法与抽象工厂方法:
工厂方法:
在这里插入图片描述
抽象工厂方法:
在这里插入图片描述

区别:

  • 工厂方法中只会提供一个抽象接口,接口的实现交给各个工厂去做,抽象类只会知道是制作一个pizza。
  • 抽象工厂是把工厂方法中的接口给拆开了,提供抽象接口的组合。会感知到制作pizza的抽象信息。
  • 抽象方法中对于每一个抽象接口的实现,利用了工厂方法的思路。

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

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

相关文章

回声状态网络(Echo State Networks,ESN)详细原理讲解及Python代码实现

回声状态网络(Echo State Networks,ESN)详细讲解及Python代码实现 1 基本概念 回声状态网络是一种循环神经网络。ESN 训练方式与传统 RNN 不同。网络结构如下图: (1)储层(Reservoir)&#x…

vue中使用js-doc

安装依赖 安装vue-template-compiler npm install ​vue-template-compiler​npm install ​vue-template-compiler​ 安装minami npm install minami 安装js-doc npm install js-doc 根目录下创建 .jsdoc.conf.json 内容: {"tags": {"all…

在Linux中创建文件的多种方法

目录 前言1 使用重定向符号 ">"2 使用文本编辑器 vi/vim3 使用 nano4 使用 echo5 使用 touch6 使用 printf7 使用 head8 使用 cat9 使用 tail10 使用 truncate结语 前言 在Linux系统中,文件的创建是日常操作中不可避免的一部分。无论是创建空文件、编…

解决MPICH的GPU初始化失败:一次深入探索

今天来分享“MPICH:MPII_Init_thread(222): gpu_init failed”这个问题的解决方式 文章目录 前言问题原因解决方案 前言 如果在安装MPICH的时候没有注意要一些选项,那么当使用mpicxx mpi_send.cpp -o send && mpirun -n 2 ./send进行编译输出的…

图片特效/增强GUI程序

程序下载地址:mendianyu/pictureConvert: 图片特效/增强GUI程序,借助百度接口实现人像动漫化,模糊图片变清晰等等功能 (github.com) 图片特效/增强GUI程序 借助百度接口实现人像动漫化,模糊图片变清晰等等功能 程序介绍 运行Ima…

LIS系统:样本采集、检验、分析、查看报告

检验科LIS系统是实验室信息管理系统,主要用于实验室检验工作流程管理、病人信息管理、检验结果查询、统计和报表打印等功能。它采用智能辅助功能,自动接收检验数据、打印检验报告,并保存检验信息的工具。同时,可根据实验室需要实现…

opencv(C++)基础用法

文章目录 前言一、opencv (C)图片基本操作1.1 读取图片并显示1.2 颜色转换1.3 图像filtering1.4 形状调整1.5 绘制 二、读取视频文件并显示三、RTSP 视频流四. 人脸检测总结 前言 学习笔记 一、opencv (C)图片基本操作 1.1 读取图片并显示 #include "opencv2/opencv.hp…

二、Java中SpringBoot组件集成接入【MySQL和MybatisPlus】

二、Java中SpringBoot组件集成接入【MySQL和MybatisPlus】 1.MySQL和MybatisPlus简介2.maven依赖3.配置1.在application.yaml配置中加入mysql配置2.新增Mybatis-Plus配置类 4.参考文章 1.MySQL和MybatisPlus简介 MySQL是一种开源的关系型数据库管理系统,被广泛应用…

Python——猜猜心里的数字(1)

首先呢,我们自定义一个数字,然后让对方猜一猜是否能猜中,接下来我们以10为例,给对方三次机会。 num10 if int(input("请猜一个数字:"))num:print("恭喜第一次就猜对了") elif int(input("猜错了&#x…

每日一题——LeetCode1128.等价多米诺骨牌对的数量

先尝试暴力解法&#xff1a; var numEquivDominoPairs function(dominoes) {var count0for(let i0;i<dominoes.length-1;i){for(let ji1;j<dominoes.length;j){if((dominoes[i][0]dominoes[j][0] && dominoes[i][1]dominoes[j][1]) || (dominoes[i][0]dominoes…

Mac下载Navicat premium提示文件损坏的解决方案

引用&#xff1a;https://blog.csdn.net/weixin_44898291/article/details/120879508 sudo xattr -r -d com.apple.quarantine

js:使用canvas画一个半圆

背景 需求需要画一个半圆&#xff0c;或者多半圆&#xff0c;其实一下子就能想到 canvas 中的圆弧&#xff0c;核心使用 context.arc context.arc(x,y,r,sAngle,eAngle,counterclockwise)接下来我们看看示例 例一 <!DOCTYPE html> <html lang"en"> &…

【野火i.MX6NULL开发板】GCC 和 Hello World

0、前言 参考资料&#xff1a; 《野火 Linux 基础与应用开发实战指南基于 i.MX6ULL 系列》PDF 第23章 1、教程

2024美赛数学建模思路 - 复盘:校园消费行为分析

文章目录 0 赛题思路1 赛题背景2 分析目标3 数据说明4 数据预处理5 数据分析5.1 食堂就餐行为分析5.2 学生消费行为分析 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 赛题背景 校园一卡通是集…

Linux学习记录——사십이 高级IO(3)--- Poll型服务器

文章目录 1、认识poll接口2、实现3、特点 1、认识poll接口 #include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout);// pollfd结构 struct pollfd {int fd; /* file descriptor */short events; /* requested events */short revents; /* returned…

BitMap源码解析

文章目录 前言数据结构添加与删除操作 JDK中BitSet源码解析重要成员属性初始化添加数据清除数据获取数据size和length方法集合操作&#xff1a;与、或、异或优缺点 前言 为什么称为bitmap&#xff1f; bitmap不仅仅存储介质以及数据结构不同于hashmap&#xff0c;存储的key和v…

5.3 Verilog 带参数例化

5.3 Verilog 带参数例化 分类 Verilog 教程 关键词&#xff1a; defparam&#xff0c;参数&#xff0c;例化&#xff0c;ram 当一个模块被另一个模块引用例化时&#xff0c;高层模块可以对低层模块的参数值进行改写。这样就允许在编译时将不同的参数传递给多个相同名字的模块…

element:日历 / 使用记录

一、预期效果 Element - The worlds most popular Vue UI framework element默认样式 目标样式 二、Calendar 属性 参数说明类型可选值默认值value / v-model绑定值Date/string/number——range时间范围&#xff0c;包括开始时间与结束时间。开始时间必须是周一&#xff0c;…

c语言线性方式初始化二维数组

线性方式初始化二维数组&#xff0c;只需要利用/与%的关系即可。具体细节文章下面会有程序的流程分析 问题起源 想要用线性方式初始化二维数组 问题分析 例如a[3][4] a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a[2][0] a[2][1] a[2][2] a[2][3]如…

Flutter-Web从0到部署上线(实践+埋坑)

本文字数&#xff1a;7743字 预计阅读时间&#xff1a;60分钟 01 前言 首先说明一下&#xff0c;这篇文章是给具备Flutter开发经验的客户端同学看的。Flutter 的诞生虽然来自 Google 的 Chrome 团队&#xff0c;但大家都知道 Flutter 最先支持的平台是 Android 和 iOS&#xff…