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

一、简单工厂模式

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.mfbz.cn/a/558359.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MYSQL之增删改查(上)

前言&#xff1a; 以下是MySQL最基本的增删改查语句&#xff0c;很多IT工作者都必须要会的命令&#xff0c;也 是IT行业面试最常考的知识点&#xff0c;由于是入门级基础命令&#xff0c;所有所有操作都建立在单表 上&#xff0c;未涉及多表操作。 1、“增”——添加数据 1.1…

【简单介绍下R-Tree】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

228 基于matlab的神经网络人脸识别

基于matlab的神经网络人脸识别。 人脸识别以视网膜、 虹膜、 指纹等生物特征的识别作为生物标识符。生物特征识别不很容易伪造、 放错位置。新型脸识别使用的方法 RobustPCA 和径向基函数网络。程序已调通&#xff0c;可直接运行。 228 人脸识别 生物特征识 神经网络 - 小红书 …

【NTN 卫星通信】NTN的信关站应该建在哪些地方

1 概述 3GPP的卫星通信讨论了透传星和再生星两种方式。透传星方式&#xff0c;卫星主要是做为中继存在&#xff0c;基本上不做通信协议的处理。再生星方式&#xff0c;gNodeB的主要功能在卫星上&#xff0c;完成通信协议的主要内容。无论是透传星还是再生星&#xff0c;都需要通…

校园小情书微信小程序源码/社区小程序前后端开源/校园表白墙交友小程序

校园小情书前端代码&#xff0c;好玩的表白墙、树洞、校园论坛&#xff0c;可独立部署&#xff0c;也可以使用我部署的后台服务&#xff0c;毕业设计的好项目。 搭建教程&#xff1a; 一、注册管理后台 1、登录小情书站点进行注册&#xff1a;https://你的域名 2、注册成功…

【JavaEE多线程】线程中断 interrupt()

系列文章目录 &#x1f308;座右铭&#x1f308;&#xff1a;人的一生这么长、你凭什么用短短的几年去衡量自己的一生&#xff01; &#x1f495;个人主页:清灵白羽 漾情天殇_计算机底层原理,深度解析C,自顶向下看Java-CSDN博客 ❤️相关文章❤️&#xff1a;清灵白羽 漾情天…

动态酷黑主页源码

效果图 PC端 &#xff08;移动端不能访问&#xff09; 部分代码 index.html <!DOCTYPE html> <html lang"zh-CN"> <head> <meta http-equiv"X-UA-Compatible" content"IEedge,chrome1"> <meta charset"ut…

java算法day58 | 单调栈part01 ● 739. 每日温度 ● 496.下一个更大元素 I

739. 每日温度 思路&#xff1a; 这道题用暴力求解法会超时。 那我们就要想如何只遍历一遍就能求解出每个位置的下一个更大值在哪呢。 主要的思想就是空间换时间。定义一个单调栈&#xff0c;每次遇到比栈顶元素小的或相等的&#xff0c;直接入栈&#xff0c;遇到比栈顶元素大的…

电学启蒙积木电子方案

东莞市酷得智能科技有限公司是一家集芯片贸易和电子方案定制开发的研发型公司&#xff0c;其中电子积木方案是酷得经营多年的其中一条比较成熟的研发线。电学积木玩具不仅仅是一种娱乐工具&#xff0c;更是一种教育工具&#xff0c;能够在孩子们的成长过程中发挥多方面的积极作…

微信小程序开发五(与springboot整合)

首先在微信开发者工具中开启不校验合法域名&#xff0c;这个才能本地访问 实现一个小功能&#xff1a; 展示数据信息&#xff0c;每条数据的颜色不一样 后端&#xff1a;springbootmybatisplusmysql 依赖&#xff1a; <dependency><groupId>com.baomidou</grou…

代码学习记录45---单调栈

随想录日记part45 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.04.17 主要内容&#xff1a;今天开始要学习单调栈的相关知识了&#xff0c;今天的内容主要涉及&#xff1a;每日温度 &#xff1b;下一个更大元素 I 739. 每日温度 496.下一个更大元素 I Topic…

powershell@命令行提示符样式配置自定义@pwsh重写prompt显示电量内存时间等信息

文章目录 abstract流行的powershell prompt模块示例 powershell原生修改Prompt函数配置文档Prompt命令来自哪里 简单修改带上电量和时间的Prompt 复杂修改预览FAQ:没有必要修改相关仓库地址样式选择平衡样式花哨样式响应性能 小结 abstract 在 PowerShell 中&#xff0c;可以通…

国家级项目管理高级认证:CSPM-4级(高级)重磅推出

本周&#xff0c;圣略CSPM资深讲师老杨&#xff0c;赴北京参加CSPM-4级高级讲师培训&#xff0c;从现场带来第1手的资料&#xff0c;与大家分享&#xff1a; CSPM-4基本要求&#xff1a; 负责实现组织战略目标&#xff0c;以成果和收益为导向&#xff0c;需具备战略解析、收益…

汇编语言学习笔记

1、NOP指令&#xff1a;号称最安全的指令&#xff0c;全名为no Operation&#xff0c;一条nop指令占用一个字节&#xff0c;什么也不做。有时编译器会使用该指令将代码对齐到偶数地址边界&#xff08;类似于内存对齐&#xff09;。IA-32处理器从偶数双字地址处加载代码和数据时…

【简单介绍下Beego框架】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

等保合规:保护企业网络安全的必要性与优势

前言 无论是多部网络安全法律法规的出台&#xff0c;还是最近的“滴滴被安全审查”事件&#xff0c;我们听得最多的一个词&#xff0c;就是“等保。” 只要你接触安全类工作&#xff0c;听得最多的一个词&#xff0c;一定是“等保。” 那么&#xff0c;到底什么是“等保”呢…

c++初阶——类和对象(上)

大家好我是小锋今天我们来学习类和对象 面向过程和面向对象初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 C是基于面向对象的&#xff0c;关注的是对象&#xff0c;将一件事情拆分成不同的对…

NASM中的-f选项

2024年4月19日&#xff0c;周五下午 -f选项 在 NASM 中&#xff0c;-f 选项用于指定输出格式或目标文件格式。这个选项允许你告诉 NASM 将汇编代码编译成特定格式的目标文件&#xff0c;以便与特定的操作系统或环境兼容。下面是 -f 选项的一些常见用法和参数&#xff1a; -f …

✌粤嵌—2024/4/11—合并区间✌

代码实现&#xff1a; /*** Return an array of arrays of size *returnSize.* The sizes of the arrays are returned as *returnColumnSizes array.* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().*/// 交换 void swap(i…

“开关是灯的日出日落,日出日落是灯的开关”

C语言刷题 day01 本篇是C语言刷题大杂烩&#xff0c;收集了笔者遇到的认为有价值的题目&#xff0c;本篇会持续更新~~ day01 至少是其他数字两倍的最大数 题目原文&#xff1a; 题意解析&#xff1a; 请你找出数组中的最大元素并检查它是否 至少是数组中每个其他数字的两倍 …