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

ops/2024/9/18 12:49:47/ 标签: 简单工厂模式, 工厂方法模式

一、简单工厂模式

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.ppmy.cn/ops/2859.html

相关文章

ChatGPT写作术:高效撰写顶级论文

ChatGPT无限次数:点击直达 ChatGPT写作术&#xff1a;高效撰写顶级论文 在当今信息爆炸的时代&#xff0c;如何撰写出高质量的论文成为许多研究者和学生的重要课题。借助人工智能技术的不断发展&#xff0c;像ChatGPT这样的语言生成模型能够为撰写论文提供有效的帮助。本文将介…

云原生(八)、Kubernetes基础(一)

K8S 基础 # 获取登录令牌 kubectl create token admin --namespace kubernetes-dashboard1、 NameSpace Kubernetes 启动时会创建四个初始名字空间 default:Kubernetes 包含这个名字空间&#xff0c;以便于你无需创建新的名字空间即可开始使用新集群。 kube-node-lease: 该…

外包干了2个月,技术倒退2年。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;20年通过校招进入深圳某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年国庆&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

Sql Server 数据库:查询表结构脚本

查询脚本: SELECT CASE WHEN col.colorder 1 THEN obj.name ELSE END AS 表名, col.colorder AS 序号 , col.name AS 列名 , ISNULL(ep.[value], ) AS 列说明 , t.name AS 数据类型 , col.length AS 长度 , ISNULL(COLUMNPROPERTY(col.id, col.name, Scale), 0) AS 小数位数…

SpringBoot + minio实现分片上传、秒传、续传

什么是minio MinIO是一个基于Go实现的高性能、兼容S3协议的对象存储。它采用GNU AGPL v3开源协议&#xff0c;项目地址是https://github.com/minio/minio。 引用官网&#xff1a; MinIO是根据GNU Affero通用公共许可证v3.0发布的高性能对象存储。它与Amazon S3云存储服务兼容…

23种设计模式-Python,优缺点场景与示例代码

今天我将与大家探讨软件开发中至关重要的一些概念——设计模式。无论你是初学者还是经验丰富的开发者&#xff0c;理解这些模式都将对你的编程技能有巨大的提升。 首先什么是设计模式&#xff1f; 设计模式是解决软件设计问题中常见问题的典型解决方案。它们是被多次实践验证…

Linux-面试题

Q1&#xff1a;什么是程序&#xff0c;什么是进程&#xff0c;有什么区别&#xff1f; 程序&#xff1a; 程序是一种静态的实体&#xff0c;它是计算机中一组有序的指令集合&#xff0c;这些指令定义了完成特定任务所需的操作序列。程序通常以某种编程语言编写&#xff0c;经过…

用python写的文本水印隐藏工具

看见一个文本水印项目&#xff1a;text_blind_watermark https://github.com/guofei9987/text_blind_watermark 假设这种场景是不是合适使用&#xff1a; 小米su7发布之前一周&#xff0c;各大博主已经已经拿到参数配置和价格表了&#xff0c;保密政策不允许博主提前发布&…

2024-Java-Maven学习笔记

Maven Maven是一个Java项目管理和构建工具&#xff0c;作用&#xff1a;定义&#xff08;规范&#xff09;项目结构、项目依赖、使用统一的方式自动化构建&#xff08;clean、compile&#xff09;。 提供了一套依赖管理机制&#xff1a;利用仓库统一管理jar包&#xff0c;利用…

[尚硅谷flink] 检查点笔记

在Flink中&#xff0c;有一套完整的容错机制来保证故障后的恢复&#xff0c;其中最重要的就是检查点。 文章目录 11.1 检查点11.1.1 检查点的保存1&#xff09;周期性的触发保存2&#xff09;保存的时间点3&#xff09;保存的具体流程 11.1.2 从检查点恢复状态11.1.3 检查点算法…

c#中怎么自动下载软件

以下是一个简单的 C# 示例&#xff0c;演示如何使用 WebClient 类下载软件&#xff1a; using System; using System.Net; class Program { static void Main(string[] args) { // 要下载的文件 URL string fileUrl "https://example.com/path/to/file"; // 本地保…

VOJ 幼儿园买玩具 题解 二进制枚举

幼儿园买玩具 代码 #include <bits/stdc.h> using namespace std; typedef long long ll; int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int n, m, k;cin >> n >> m >> k;vector<vector<int>> v(n 1);for (int i 1; i …

Llama2模型本地部署(Mac M1 16G)

环境准备 环境&#xff1a;Mac M1 16G、Conda Conda创建环境配置 使用Anaconda-Navigator创建python 3.8环境 切换到新建的conda环境&#xff1a; conda activate llama38 llama.cpp 找一个目录&#xff0c;下载llama.cpp git clone https://github.com/ggerganov/llama.…

Flume

目录 Flume概述 Flume架构 Flume案例 入门案例 实时监控单个追加文件 实时监控目录下多个新文件 实时监控目录下的多个追加文件 Flume事务 Flume内部原理 Sorce ->> Channel Channel ->> Sink Flume拓扑结构 复制和多路复用 负载均衡和故障转移 聚合…

写代码的修养

看山是山&#xff0c;看水是水 此境界 对业务的思考是浅层的&#xff0c;代码写的不通用&#xff0c;扩展性差&#xff0c;表现在无设计模式 看山不是山&#xff0c;看水不是水 此境界 对业务的思考是中层的&#xff0c;代码写的通用&#xff0c;扩展性好&#xff0c;表现为…

【MogDB】在ORACLE和MogDB中查看存储过程出参游标数据的方式

一、前言 使用ORACLE作为数据库的应用软件中&#xff0c;偶尔会遇到使用游标作为出参的存储过程&#xff0c;这种存储过程迁移到MogDB并不需要进行改造&#xff0c;但是在开发这样的存储过程时&#xff0c;开发人员偶尔会想要在数据库中测试执行一下&#xff0c;看看游标中的数…

水经微图IOS版5.2.0发布

随时随地&#xff0c;微图一下&#xff01; 水经微图&#xff08;简称“微图”&#xff09;IOS新版已上线。 在该版本中主要新增图层树节点排序功能、常规&#xff08;矩形、圆、椭圆、扇形&#xff09;绘制功能、地形夸张等主要功能。 当前版本 当前版本号为&#xff1a;5…

[lesson43]继承的概念和意义

继承的概念和意义 类之间的组合关系 组合关系的特点 将其他类的对象作为当前类的成员使用当前类的对象与成员对象的生命期相同成员对象在用法上与普通对象完全一致 惊艳的继承 面相对象中的继承指类之间的父子关系 子类拥有父类的所有属性和行为子类就是一种特殊的父类子类…

【MATLAB源码-第22期】基于matlab的手动实现的(未调用内置函数)CRC循环码编码译码仿真。

1、算法描述 循环码是线性分组码的一种&#xff0c;所以它具有线性分组码的一般特性&#xff0c;此外还具有循环性。循环码的编码和解码设备都不太复杂&#xff0c;且检(纠)错能力强。它不但可以检测随机的错误&#xff0c;还可以检错突发的错误。&#xff08;n,k&#xff09;…

Linux Debian安装教程

Debian 是一个免费的开源操作系统&#xff0c;是最古老的 Linux 发行版之一&#xff0c;于 1993 年由 Ian Murdock 创建。它采用了自由软件协议&#xff0c;并且由志愿者社区维护和支持。Debian 的目标是创建一个稳定、安全且易于维护的操作系统&#xff0c;以自由软件为基础&a…