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

news2025/1/18 11:47:49

一、简单工厂模式

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 stub
		SimpleFactory 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 {

	@Override
	public 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 {
	@Override
	public 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.coloradmin.cn/o/1608364.html

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

相关文章

011、Python+fastapi,第一个后台管理项目走向第11步:建立python+fastapi项目,简单测试一下

一、说明 本文章就是记录自己的学习过程&#xff0c;如果有用您可以参考&#xff0c;没用你就略过&#xff0c;没有好与不好之分&#xff0c;今天主要是参考了gitee上的一些项目&#xff0c;一步一步的往后i建立 对于学习来说&#xff0c;如果您有java c等经验&#xff0c;py…

注意力机制基本思想(二)(自注意力机制)

​&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;《深度学习基础知识》 相关专栏&#xff1a; ⚽《机器学习基础知识》 &#x1f3d0;《机器学习项目实战》 &#x1f94e;《深度学习项目实…

河北专升本(c语言各种编程题)

目录 第一类、递归调用 第二类、特殊数字 第三类、多维数组 第四类、字符处理 第五类、数学问题 第六类、排序算法 第七类、循环问题 第八类、进制转换 第九类、实际应用 第十类、图形输出 第一类、递归调用 1.汉诺塔&#xff1a;请输入盘子数&#xff0c;输出盘子移动…

JVM 性能调优命令(jps,jinfo,jstat,jstack,jmap)

常用命令&#xff1a;jps、jinfo、jstat、jstack、jmap jps jps查看java进程及相关信息 jps -l 输出jar包路径&#xff0c;类全名 jps -m 输出main参数 jps -v 输出JVM参数jps命令示例 显示本机的Java虚拟机进程&#xff1a; # jps 15729 jar 92153 Jps 90267 Jstat显示主类…

【QT进阶】Qt Web混合编程之html、 js的简单交互

往期回顾 【QT进阶】Qt Web混合编程之VS2019 CEF的编译与使用&#xff08;图文并茂超详细介绍&#xff09;-CSDN博客【QT进阶】Qt Web混合编程之QWebEngineView基本用法-CSDN博客【QT进阶】Qt Web混合编程之CMake VS2019编译并使用QCefView&#xff08;图文并茂超详细版本&…

Mamba论文笔记

Mamba论文 结合序列建模任务通俗地解释什么是状态空间模型&#xff1f;创新点和贡献 为什么Mamba模型擅长捕获long range dependencies&#xff1f; 结合序列建模任务通俗地解释什么是状态空间模型&#xff1f; 状态空间模型&#xff08;State Space Model, SSM&#xff09;是…

css设置文字撑满盒子

效果如上&#xff1a; <div style"width: 250px;background-color:red;text-align-last:justify;word-break: keep-all;">为中国崛起而读书</div>

Git常见命令行操作和IDEA图形化界面操作

设置Git用户名和标签 在安装完Git以后需要设置用户和签名&#xff0c;至于为什么要设置用户签名可以看一下这篇文章【学了就忘】Git基础 — 11.配置Git用户签名说明 - 简书 (jianshu.com) 基本语法&#xff1a; git config --global user.name 用户名 git config --global u…

漳州不饱和聚酯树脂首次出口非洲

我可以确认&#xff0c;2024年4月中旬左右&#xff0c;漳州新阳科技有限公司制造的不饱和聚酯树脂产品首次出口至非洲市场。这批树脂共计167.2吨&#xff0c;经过漳州市古雷海关的监管放行后&#xff0c;被运往非洲国家阿尔及利亚和莫桑比克。这一举动标志着漳州企业在拓展国际…

深度学习基础之《TensorFlow框架(12)—图片数据》

一、图像基本知识 1、如何转换图片文件 回忆&#xff1a;之前我们在特征抽取中讲过如何将文本处理成数据 思考&#xff1a;如何将图片文件转换成机器学习算法能够处理的数据&#xff1f; 我们经常接触到的图片有两种&#xff0c;一种是黑白图片&#xff08;灰度图&#xff09;…

element-ui form表单自定义label的样式、内容

element-ui form表单自定义label的样式、内容 效果截图 代码 <el-form size"small" :inline"true" label-width"120px"><el-form-item prop"name"><div slot"label"><i style"color: red;"…

数据结构·一篇搞定顺序表!

大家好啊&#xff0c;几日不见&#xff0c;甚是想念&#xff0c;从这一篇文章开始&#xff0c;我们就要进入数据结构了哦&#xff0c;那么我们废话不多说&#xff0c;今天我们一起来搞定顺序表&#xff01;&#xff01;&#xff01; 1. 顺序表概念及结构 顺序表是一种线性结…

自定义数据 微调CLIP (结合paper)

CLIP 是 Contrastive Language-Image Pre-training 的缩写&#xff0c;是一个擅长理解文本和图像之间关系的模型&#xff0c;下面是一个简单的介绍&#xff1a; 优点&#xff1a; CLIP 在零样本学习方面特别强大&#xff0c;它可以&#xff08;用自然语言&#xff09;给出图像…

【文件系统】 F2FS文件系统学习

一、基本介绍 1、F2FS History F2FS&#xff08;Flash Friendly File System&#xff09;是专门为Nand Flash设计的一个日志型文件系统&#xff0c;于2012年12月合入Linux3.8内核&#xff0c;Google也在2018年&#xff08;Android P&#xff09;将其吸收到安卓原生版本中&…

【DL水记】循环神经网络RNN的前世今生,Transformer的崛起,Mamba模型

文章目录 RNN网络简介传统RNN网络结构RNN的分类 长-短期记忆网络 (LSTM)GRU网络横空出世的Transformer网络Self-AttentionVisionTransformer Mamba模型Reference: RNN网络简介 “当人类接触新事物时&#xff0c;他们不会从头开始思考。就像你在阅读这篇文章时&#xff0c;你会根…

最新版的GPT-4.5-Turbo有多强

OpenAI再次用实力证明了&#xff0c;GPT依然是AI世界最强的玩家&#xff01;在最新的AI基准测试中&#xff0c;OpenAI几天前刚刚发布的GPT-4-Turbo-2024-04-09版本&#xff0c;大幅超越了Claude3 Opus&#xff0c;重新夺回了全球第一的AI王座&#xff1a; 值得一提的是&#xf…

Assign Memory Resources to Containers and Pods

minikube addons enable metrics-server minikube addons enable metrics-server 是一个命令&#xff0c;用于在 Minikube 环境中启用 metrics-server 插件。 Minikube 是一个工具&#xff0c;可以在本地轻松创建和管理单节点 Kubernetes 集群&#xff0c;适合开发和测试。Mini…

二叉树进阶题目

1还原二叉树 #include<bits/stdc.h> using namespace std; const int N1e310; char pre[N],mid[N]; int w[N]; int ans; struct node{int l,r; }t[N]; int build(int prel,int prer,int midl,int midr){int ascpre[prel];int posw[asc];if(midl<pos)t[asc].lbuild(pre…

从 Elastic 的 Go APM 代理迁移到 OpenTelemetry Go SDK

作者&#xff1a;来自 Elastic Damien Mathieu 正如我们之前所分享的&#xff0c;Elastic 致力于帮助 OpenTelemetry&#xff08;OTel&#xff09;取得成功&#xff0c;这意味着在某些情况下构建语言 SDK 的分发版本。 Elastic 在观察性和安全数据收集方面战略性地选择了 OTel…

深入挖掘C语言 ----动态内存分配

开篇备忘录: "自给自足的光, 永远都不会暗" 目录 1. malloc和free1.1 malloc1.2 free 2. calloc和realloc2.1 calloc2.2 realloc 3. 总结C/C中程序内存区域划分 正文开始 1. malloc和free 1.1 malloc C语言提供了一个动态开辟内存的函数; void* malloc (size_t s…