【创建型模式】工厂方法模式

一、简单工厂模式

1.1 简单工厂模式概述

        简单工厂模式又叫做静态工厂方法模式

  • 目的:定义一个用于创建对象的接口。
  • 实质:由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

  • 简单工厂模式基本实现流程
  • 1.具体产品类:将需要创建的各种不同产品对象的相关代码封装到具体产品类中;
  • 2.抽象产品类:将具体产品类公共的代码进行抽象和提取后封装在一个抽象产品类中;
  • 3.工厂类:提供一个工厂类用于创建各种产品,在工厂中提供一个创建产品的工厂方法,该方法可以根据所传入参数的不同创建不同的具体产品对象。
  • 4.客户端:指需调用工厂类的工厂方法并传入相应的参数即可得到一个产品对象。

        创建对象与适用对象

  • Java语言创建对象的几种方式
    • 1.用new关键字直接创建对象;
    • 2.通过反射机制创建对象;
    • 3.通过克隆方法创建对象;
    • 4.通过工厂类创建对象。
  • 将对象的创建与使用分离的其他好处
    • 1.防止用来实例化一个类的数据和代码在多个类中到处都是,可以将有关创建的知识搬移到一个工厂类中,解决代码重复、创建蔓延的问题;
    • 2.构造函数的名字都与类名相同,从构造函数和参数列表中大家很难里哦阿姐不同构造函数所构造的产品的差异->将对象的创建过程封装在工厂类中,可以提供一系列名字完全不同的工厂方法,每一个工厂方法对应一个构造函数,客户端可以以一种更加可读、易懂的方式来创建对象。
  • 何时不需要工厂?
    • 1.无须为系统中的每一个类都配备一个工厂类;
    • 2.如果一个类很简单,而且不存在太多变化,其构造过程也很简单,此时就无须为其提供工厂类,直接在使用之前实例化即可;
    • 3.否则会导致工厂泛滥,增加系统的复杂度。

        简单工厂模式的简化:将抽象产品类和工厂类合并,将静态工厂方法移至抽象产品类中。

  • 简单工厂模式的优缺点
    • 优点
      • 1.实现了对象创建和使用的分离
      • 2.客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可
      • 3.通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性
    • 缺点
      • 1.工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响
      • 2.增加系统中类的个数(引入了新的工厂类),增加了系统的复杂度和理解难度
      • 3.系统扩展困难,一旦添加新产品不得不修改工厂逻辑
      • 4.由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构,工厂类不能得到很好地扩展
  • 适用环境
    • 1.工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂
    • 2.客户端只知道传入工厂类的参数,对于如何创建对象并不关心

 1.2 代码实现

        简单工厂模式包含3个角色:

  • 工厂角色
  • 抽象产品角色
  • 具体产品角色
        1.2.1 抽象产品角色(Pizza:将具体行为抽象出来)
package factory.simple.pizzaFactory;
//抽象产品
import java.util.ArrayList;public abstract class Pizza {String name;String dough;//面团String sauce;//酱料ArrayList toppings=new ArrayList();//佐料public void prepare(){System.out.println("preparing "+ name); System.out.println("Tossing dough... "); System.out.println("adding sauce... "); for (int i=0;i<toppings.size();i++)System.out.println(" "+toppings.get(i));}public  void bake(){System.out.println("Bake for 25minutes at 350"); }public  void cut(){System.out.println("cutting the pizza"); }public  void box(){System.out.println("place pizza in officical Pizza box");}public String getName(){return name;}
}
        1.2.2 工厂角色(SimpleFactory:产生Pizza)
package factory.simple.pizzaFactory;
//工厂角色
public class SimpleFactory {public Pizza createPizza(String type) {Pizza pizza = null;if (type.equals("cheese")) {pizza = new CheesePizza();} else if (type.equals("pepperoni")) {pizza = new PepperoniPizza();} else if (type.equals("Greek")) {pizza = new GreekPizza();} else if (type.equals("clam")) {pizza = new ClamPizza();} else if (type.equals("veggie")) {pizza = new VeggiePizza();}return pizza;}
}
        1.2.3 具体产品角色(CheesePizza、ClamPizza、GreekPizza、PepperoniPizza、VeggiePizza)
package factory.simple.pizzaFactory;
//具体产品类
public class CheesePizza extends Pizza {public void prepare(){System.out.println("Cheese比萨原材料正在准备中....");}public void bake(){System.out.println("Cheese比萨正在焙烤中....");}public void cut(){System.out.println("Cheese比萨,切块中....");}public void box(){System.out.println("Cheese比萨,正在打包....");}}
package factory.simple.pizzaFactory;
//具体产品类
public class ClamPizza extends Pizza {public void prepare(){System.out.println("Clam比萨原材料正在准备中....");}public void bake(){System.out.println("Clam比萨正在焙烤中....");}public void cut(){System.out.println("Clam比萨,切块中....");}public void box(){System.out.println("Clam比萨,正在打包....");}}
package factory.simple.pizzaFactory;
//具体产品类
public class GreekPizza extends Pizza {public void prepare(){System.out.println("Greek比萨原材料正在准备中....");}public void bake(){System.out.println("Greek比萨正在焙烤中....");}public void cut(){System.out.println("Greek比萨,切块中....");}public void box(){System.out.println("Greek比萨,正在打包....");}}
package factory.simple.pizzaFactory;
//具体产品类
public class PepperoniPizza extends Pizza {public void prepare(){System.out.println("Pepperoni比萨原材料正在准备中....");}public void bake(){System.out.println("Pepperoni比萨正在焙烤中....");}public void cut(){System.out.println("Pepperoni比萨,切块中....");}public void box(){System.out.println("Pepperoni比萨,正在打包....");}}
package factory.simple.pizzaFactory;
//具体产品类
public class VeggiePizza extends Pizza {public void prepare(){System.out.println("Veggie比萨原材料正在准备中....");}public void bake(){System.out.println("Veggie比萨正在焙烤中....");}public void cut(){System.out.println("Veggie比萨,切块中....");}public void box(){System.out.println("Veggie比萨,正在打包....");}
}
        1.2.4 客户端类(PizzaStore:产生Pizza)
package factory.simple.pizzaFactory;
//客户端,取得Pizza
public class PizzaStore {SimpleFactory  sf;public PizzaStore(SimpleFactory sf) {super();this.sf = sf;}Pizza orderPizza(String name){  Pizza pizza=sf.createPizza(name);	  	  pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;}}
        1.2.5 main方法实现简单工厂模式(Test)
package factory.simple.pizzaFactory;
import factory.simple.pizzaFactory.PizzaStore;
public class Test {public static void main(String[] args) {// TODO Auto-generated method stubSimpleFactory sf=new SimpleFactory();//创建一个披萨工厂PizzaStore store=new PizzaStore(sf);//产生披萨制作商店store.orderPizza("cheese");//点餐}
}
        1.2.6 UML图 

1.3 代码结构

二、工厂方法模式

2.1 工厂方法模式概述

        工厂方法模式的定义-意图:一个用于创建对象的接口,让子类“决定”实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。“决定”并不是模式允许子类本身再运行时做决定,而是指再编写创建者类时,不需要知道实际创建的产品时哪一个。(类创建型模式)

        工厂方法模式简称工厂模式、虚拟构造器模式、多态工厂模式。其中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象目的是将产品类的实例化操作延迟到工厂类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

  • 工厂方法模式优缺点
    • 优点
      • 1.工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节;
      • 2.能够让工厂自主确定创建这个对象的细节则完全封装在具体工厂内部。3.在系统中加入新产品时,完全符合开闭原则。
    • 缺点
      • 1.系统中类的个数将成为对增加,在一定程度上增加了系统的复杂度,会给系统带来一些额外的开销;
      • 2.增加了系统的抽象性和理解难度。
  • 适用环境
    • 1.客户端不知道它所需要的对象的类(客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体产品对象由具体工厂类创建。)
    • 2.抽象工厂类通过其子类来指定创建哪个对象。

2.2 代码实现

        工厂方法模式包含四个角色:

  • 抽象产品(Product):定义产品的接口,是工厂方法模式所创建对象的超类型,即产品对象的共同父类或接口;
  • 具体产品类(Concreteproduct):具体产品实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,它们之间往往一一对应;
  • 抽象工厂类(Factory):声明了工厂方法,用于返回一个产品,它是工厂方法模式的核心,任何在模式中创建对象的工厂类都必须实现该接口;(类似工厂总部)
  • 具体工厂类(Concretefactory):抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户调用,返回一个具体产品类的实例。(类似各个子工厂)
        2.2.1 抽象产品类(Pizza)
package factory.factorymethod.pizza;
import java.util.ArrayList;
//抽象产品类:披萨
public abstract class Pizza {String name;String dough;//面团String sauce;//酱料//下行代码就是得到不同店的佐料制作方式ArrayList toppings=new ArrayList();//佐料public void prepare(){System.out.println("preparing "+ name); System.out.println("Tossing dough... "); System.out.println("adding sauce... "); //选择不同店的佐料制作方式for (int i=0;i<toppings.size();i++)System.out.println(" "+toppings.get(i));}public  void bake(){System.out.println("Bake for 25minutes at 350"); }public  void cut(){System.out.println("cutting the pizza"); }public  void box(){System.out.println("place pizza in officical Pizza box");}public String getName(){return name;}
}
        2.2.2 具体产品类(ChicagoCheesePizza、ChicagoPepperoniPizza、NYCheesePizza、NYPepperoniPizza)
package factory.factorymethod.pizza;
//具体产品类:芝加哥cheese披萨
public class ChicagoCheesePizza extends Pizza {public ChicagoCheesePizza() {name="ChicagoCheesePizza";dough="Chicago style 面团";sauce="Chicago style 酱汁";toppings.add("NYCheesePizzaChicagoCheesePizza");}
}
package factory.factorymethod.pizza;
//具体产品类:芝加哥Pepperoni披萨
public class ChicagoPepperoniPizza extends Pizza {public ChicagoPepperoniPizza() {name="ChicagoPepperoniPizza";dough="Chicago style 面团";sauce="Chicago style 酱汁";toppings.add("Chicago style PepperoniPizza");}}
package factory.factorymethod.pizza;
//具体产品类:纽约Cheese披萨
public class NYCheesePizza extends Pizza {public NYCheesePizza() {name="NYCheesePizza";dough="NY style 面团";sauce="NY style 酱汁";toppings.add("NYCheesePizza");}
}
package factory.factorymethod.pizza;
//具体产品类:纽约Pepperoni披萨
public class NYPepperoniPizza extends Pizza {public NYPepperoniPizza() {name="NYPepperoniPizza";dough="NY style 面团";sauce="NY style 酱汁";toppings.add("NYPepperoniPizza");}
}
        2.2.3 抽象工厂类(PizzaStore)
package factory.factorymethod.pizza;
//抽象工厂类:披萨商店(总部)
public abstract class PizzaStore {	public final Pizza orderPizza(String name){  // 把创建Pizza从工厂中移回来 Pizza pizza=createPizza(name);	  	  pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;}public abstract Pizza createPizza(String name);
}
        2.2.4 具体工厂类(ChicagoPizzaStore、NYPizzaStore)
package factory.factorymethod.pizza;
//具体工厂类:芝加哥披萨店
public class ChicagoPizzaStore extends PizzaStore {@Overridepublic Pizza createPizza(String name) {Pizza pizza=null;if(name.equals("cheese"))pizza=new ChicagoCheesePizza();else if(name.equals("pepperoni"))pizza=new ChicagoPepperoniPizza();return pizza;}}
package factory.factorymethod.pizza;
//具体工厂类:纽约披萨店
public class NYPizzaStore extends PizzaStore {@Overridepublic Pizza createPizza(String name) {Pizza pizza=null;if(name.equals("cheese"))pizza=new NYCheesePizza();		   else if(name.equals("pepperoni"))pizza=new NYPepperoniPizza();	   return pizza;}
}
        2.2.5 main方法实现工厂方法模式(Test)
package factory.factorymethod.pizza;public class Test {public static void main(String[] args) {NYPizzaStore ns=new NYPizzaStore();ns.orderPizza("cheese");ChicagoPizzaStore cs=new ChicagoPizzaStore();cs.orderPizza("cheese");}
}
        2.2.6 UML图

2.3 代码结构

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

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

相关文章

MT2046 巨大的错误

1.暴力代码 2/10 #include <bits/stdc.h> using namespace std; int n; int a[25]; int b[25]; int ans 0; bool err() {for (int i 1; i < n; i){if (a[i] b[i]){return false;}}return true; } int main() {cin >> n;for (int i 1; i < n; i){a[i] i…

【Mysql数据库进阶01】窗口函数

窗口函数 1 定义2 聚合窗口函数2.1 默认效果/累计效果2.2 前面两行当前一行2.3 前面一行当前一行后面一行 3 排名窗口函数3.1 排名函数3.1.1 排名函数案例 3.2 累积分布 4 取值窗口函数 1 定义 完整的窗口函数定义如下: window_function([expression]) over(partition byorde…

【nnUNetv2进阶】五、nnUNetv2 魔改网络-小试牛刀-加入注意力机制SpatialAttention

nnUNet是一个自适应的深度学习框架&#xff0c;专为医学图像分割任务设计。以下是关于nnUNet的详细解释和特点&#xff1a; 自适应框架&#xff1a;nnUNet能够根据具体的医学图像分割任务自动调整模型结构、训练参数等&#xff0c;从而避免了繁琐的手工调参过程。 自动化流程&a…

H3C交换机ACL部分规则不生效问题

问题描述 H3C交换机ACL部分规则不生效问题 H3C交换机配置ACL后&#xff0c;规则在100左右&#xff0c;约10个接口下调用后&#xff0c;单独 permit 4个指定源、目IP地址的流量。但是只有前2个生效&#xff0c;后边2个相同的配置不生效。 问题原因 ACL性能不够的问题 dis q…

刀具表面上的微结构

刀具表面微结构通常指在刀具表面对特定功能设计的微观纹理&#xff0c;这些纹理可以是沟槽、凹坑、凸起或任何其他形式的微观图案。这些微结构的设计和应用是为了改善刀具的切削性能&#xff0c;减少切削力和切削温度&#xff0c;提高切削效率和精度&#xff0c;同时降低切削液…

前端常见面试题:HTML+CSS

1. title与h1的区别、b与strong的区别、i与em的区别&#xff1f; title与h1的区别&#xff1a; title标签用于定义整个HTML文档的标题&#xff0c;它显示在浏览器窗口的标题栏或者标签页上。每个HTML文档只应该有一个title标签&#xff0c;它对搜索引擎优化&#xff08;SEO&a…

mysql performance schema 实践

参考MySQL调优性能监控之performance schema,做了一些扩展 1 2、哪类SQL的平均响应时间最多 SUM_NO_INDEX_USED>0用来过滤那些没有使用的查询。 SELECT SCHEMA_NAME,DIGEST_TEXT,AVG_TIMER_WAIT,MAX_TIMER_WAIT,SUM_LOCK_TIME,SUM_ERRORS ,SUM_SELECT_FULL_JOIN,SUM_NO_IND…

大规模端云协同智能计算(大小模型端云协同联合学习)

原文作者&#xff1a;上海交通大学 吴帆 0 引言 目前&#xff0c;许多智能技术已经走入人们的日常生活&#xff0c;例如交互式商品推荐、人脸识别、语音识别、体征观测、疾病诊断、智能决策等&#xff0c;这些智能技术在为我们生活带来极大便利的同时&#xff0c;也深刻改变了…

前端开发攻略---实现与ChatGPT同款光标闪烁打字效果。

1、演示 2、实现代码 <!DOCTYPE html> <html lang"ch-ZN"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport" content"widt…

Spingbot项目配置mySQL或postgresSQL详解

1&#xff1a;postgresql库: yml文件 探索PostgreSQL&#xff1a;从基础到实践&#xff08;简单实例&#xff09; # PageHelper分页插件 pagehelper:helperDialect: postgresqlreasonable: truesupportMethodsArguments: trueparams: countcountSql# 数据源配置 spring:datas…

SQLite作为应用程序文件格式(二十八)

返回&#xff1a;SQLite—系列文章目录 上一篇:SQLite数据库中JSON 函数和运算符(二十七) 下一篇&#xff1a;SQLite—系列文章目录 摘要 具有定义架构的 SQLite 数据库文件 通常是一种出色的应用程序文件格式。 以下是十几个原因&#xff1a; 简化的应用程序开发单文…

web安全学习笔记(9)

记一下第十三课的内容。 准备工作&#xff1a;在根目录下创建template目录&#xff0c;将login.html放入其中&#xff0c;在该目录下新建一个reg.html。在根目录下创建一个function.php 一、函数声明与传参 PHP中的函数定义和其他语言基本上是相同的。我们编辑function.php …

机器学习引领金融革命:重塑金融服务领域新格局,开启智能化新篇章

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

element-ui报表合计逻辑踩坑

element-ui报表合计逻辑踩坑 1.快速实现一个合计 ​ Element UI所提供的el-table中提供了方便快捷的合计逻辑实现&#xff1a; ​ https://element.eleme.cn/#/zh-CN/component/table ​ 此实现方法在官方文档中介绍详细&#xff0c;此处不多赘述。 ​ 这里需要注意&#x…

【C语言】万字讲解函数栈帧的创建与销毁

目录 前言 一、什么是函数栈帧&#xff1f; 二、理解函数栈帧能解决什么问题呢 三、函数栈帧的创建和销毁解析 3.1 什么是栈&#xff1f; 3.2 认识相关寄存器和汇编指令 3.3 剖析函数栈帧的创建和销毁 3.3.1 esp寄存器与ebp寄存器的重要性 3.3.2 函数的调用堆栈 3.3.…

SAP MRP-MD01与MRP LIVE-MD01N简介

自从SAP推出HANA以后,无论在做项目还是在面试的时候都会遇到一个问题,就是MRP和MRP LIVE 有什么区别。通常顾问都知道MRPLIVE是运行在内存中的,运行效率会优于传统的MRP。经历了很多家的公司都是HANA的系统,基本都很少会用到MRP LIVE,百分之98%都还是在用传统的MRP在跑物料…

利用 Python 开发手机 App 实战

Python语言虽然很万能&#xff0c;但用它来开发app还是显得有点不对路&#xff0c;因此用Python开发的app应当是作为编码练习、或者自娱自乐所用&#xff0c;加上目前这方面的模块还不是特别成熟&#xff0c;bug比较多&#xff0c;总而言之&#xff0c;劝君莫轻入。 准备工作 …

c++的学习之路:24、 二叉搜索树概念

摘要 本章主要是讲一下二叉搜索树的实现 目录 摘要 一、二叉搜索树概念 二、 二叉搜索树操作 1、二叉搜索树的查找 2、二叉搜索树的插入 3、二叉搜索树的删除 三、二叉搜索树的实现 1、插入 2、中序遍历 3、删除 4、查找 四、二叉搜索树的递归实现 1、插入 2、删…

Leetcode刷题之合并两个有序数组

Leetcode刷题之合并两个有序数组 一、题目描述二、题目解析 一、题目描述 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数…

去哪网拿去花不能提现,只能用于透支消费,那么拿去花提现是怎么实现呢?

去哪网拿去花不能提现&#xff0c;只能用于透支消费&#xff0c;那么拿去花提现是怎么实现呢&#xff1f; 申请携程拿去花之后&#xff0c;有一些人就会想着把钱提现出来拿去用。一般来说&#xff0c;他们都是通过线下门店来提现拿去花&#xff0c;拿去花允许用户先消费后付款&…