【创建型模式】抽象工厂模式

一、抽象工厂模式概述

        抽象工厂模式定义提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

  • 模式动机
    • 1.当系统提供的工厂生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构、属于不同类型的具体产品时就可以使用抽象工厂模式;
    • 2.抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形式。
  • 抽象工厂:一个工厂可以生产一系列(一族产品),极大减少了工厂类的数量。又叫做工具模式:抽象工厂模式中的具体工厂不只是创建一种产品,她负责一族产品;当一个工厂等级结构可以创建出分属于不同产品登记结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、更有效率。

        产品族是指位于不同等级结构中,功能相关联的产品组成的家族。

        产品等级:产品的继承结构。

  • 开闭原则的倾斜性
    • 1.增加产品族:抽象工厂模式很好地支持了开闭原则,只需要增加具体产品并对应增加了一个新的具体工厂,对已有的代码无须做任何修改。
    • 2.增加新的产品等级结构:需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,违背了开闭原则。
  • 抽象工厂模式的优缺点
    • 优点
      • 1.隔离了具体类的生成,使得客户端并不需要知道什么被创建;
      • 2.当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象;
      • 3.增加新的产品族很方便,无需修改已有系统,符合开闭原则。
    • 缺点
      • 增加心得产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便。违背了开闭原则。
  • 模式适用环境
    • 1.当一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节;
    • 2.系统中有多于一个的产品族,但每次只使用其中一个产品族;
    • 3.属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来;
    • 4.产品等级结构稳定,在设计完成之后不会向系统中增加新的产等级结构或者删除已有的产品等级结构。

二、代码实现

        结构包含四个角色:

  • 抽象工厂(Abstract Factory):一个工厂可以生产一系列(一族产品),极大减少了工厂类的数量。
  • 具体工厂(ConcreteFactory):实现了在抽象工厂中声明的创建产品的方法,生成了一组具体产品,这些产品构成了一个产品族,每个产品都位于某个产品等级结构中。
  • 抽象产品(AbstractProduct):它为每种产品声明接口,在抽象产品中声明了产品的所有业务方法。
  • 具体产品(Concrete Product​​​​​​​):定义具体工厂生产的具体产品对象,实现在抽象产品接口中声明的业务方法。
        2.1 抽象工厂(两个抽象工厂:原料工厂和披萨总店)
package abstractFactory.Pizza;
//抽象工厂:披萨原料工厂
public interface PizzaIngredientFactory {
	//封装了制造产品原料的方法,其中每个原料都是一个类
	public Dough createDough();//面团
	public Sauce createSauce();//酱料
	public Cheese createCheese();//芝士
	public Clams createClam();
}
package abstractFactory.Pizza;
//抽象工厂:抽象披萨店(总店)
public abstract class PizzaStore {
	//生产具体类型的披萨店(每一个子店口味不一样,这里就是产生不同子店)
	protected abstract Pizza createPizza(String item);
 
	public Pizza orderPizza(String type) {
		Pizza pizza = createPizza(type);
		System.out.println("--- Making a " + pizza.getName() + " ---");
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
}
        2.2 具体工厂(芝加哥原料厂、纽约原料厂和芝加哥分店、纽约分店)
package abstractFactory.Pizza;
//芝加哥原料工厂
public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory {

	@Override
	public Dough createDough() {
		// TODO Auto-generated method stub
		return new ThickCrustDough();
	}

	@Override
	public Sauce createSauce() {
		// TODO Auto-generated method stub
		return new PlumTomatoSauce();
	}

	@Override
	public Cheese createCheese() {
		// TODO Auto-generated method stub
		return new MozzarellaCheese();
	}

	@Override
	public Clams createClam() {
		// TODO Auto-generated method stub
		return new FrozenClams();
	}

}
package abstractFactory.Pizza;
//纽约原料工厂
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {

	@Override
	public Dough createDough() {
		// TODO Auto-generated method stub
		return new ThinCrustDough();
	}

	@Override
	public Sauce createSauce() {
		// TODO Auto-generated method stub
		return new MarinaraSauce();
	}

	@Override
	public Cheese createCheese() {
		// TODO Auto-generated method stub
		return new ReggianoCheese();
	}

	@Override
	public Clams createClam() {
		// TODO Auto-generated method stub
		return new FreshClams();
	}

}
package abstractFactory.Pizza;
//具体披萨分店:芝加哥分店
public class ChicagoPizzaStore extends PizzaStore {

	@Override
	protected Pizza createPizza(String item) {
		// TODO Auto-generated method stub
		Pizza pizza = null;
		PizzaIngredientFactory ingredientFactory =
		new ChicagoPizzaIngredientFactory();
 
		if (item.equals("cheese")) {
 
			pizza = new CheesePizza(ingredientFactory);
			pizza.setName("Chicago Style Cheese Pizza");
 
		} else if (item.equals("clam")) {
 
			pizza = new ClamPizza(ingredientFactory);
			pizza.setName("Chicago Style Clam Pizza");
		
		}
		return pizza;
	}
}
package abstractFactory.Pizza;
//具体披萨分店:纽约分店
public class NYPizzaStore extends PizzaStore {

	@Override
	protected Pizza createPizza(String item) {
		// TODO Auto-generated method stub
		Pizza pizza = null;
		PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
		if (item.equals("cheese")) {
			  
			pizza = new CheesePizza(ingredientFactory);
			pizza.setName("New York Style Cheese Pizza");
  
		} else if (item.equals("clam")) {
 
			pizza = new ClamPizza(ingredientFactory);
			pizza.setName("New York Style Clam Pizza");
 
		}
		return pizza;

	}

}
        2.3 抽象产品(原料抽象产品:Dough、Sauce、Cheese、Clam;披萨抽象产品:Pizza) 
package abstractFactory.Pizza;
//抽象产品:披萨原料接口,面团
public interface Dough {
	public String toString();
}
package abstractFactory.Pizza;
//抽象产品:披萨原料接口,酱料
public interface Sauce {
	public String toString();
}
package abstractFactory.Pizza;
//抽象产品:披萨原料接口,芝士
public interface Cheese {
	public String toString();
}
package abstractFactory.Pizza;
//抽象产品:,披萨原料接口
public interface Clams {
	public String toString();
}
package abstractFactory.Pizza;
//抽象产品:披萨抽象类
public abstract class Pizza {
	String name;
	Dough dough;
	Sauce sauce;
	Cheese cheese;
	Clams clam;
 
	abstract void prepare();
 
	void bake() {
		System.out.println("Bake for 25 minutes at 350");
	}
 
	void cut() {
		System.out.println("Cutting the pizza into diagonal slices");
	}
 
	void box() {
		System.out.println("Place pizza in official PizzaStore box");
	}
 
	void setName(String name) {
		this.name = name;
	}
 
	String getName() {
		return name;
	}
 
	public String toString() {
		StringBuffer result = new StringBuffer();
		result.append("---- " + name + " ----\n");
		if (dough != null) {
			result.append(dough);
			result.append("\n");
		}
		if (sauce != null) {
			result.append(sauce);
			result.append("\n");
		}
		if (cheese != null) {
			result.append(cheese);
			result.append("\n");
		}
		if (clam != null) {
			result.append(clam);
			result.append("\n");
		}
		return result.toString();
	}
}
        2.4 具体产品(具体原料:ThickCrustDough、ThinCrustDough、PlumTomatoSauce、MarinaraSauce、MozzarellaCheese、ReggianoCheese、FrozenClams、FreshClams;具体披萨:CheesePizza、ClamPizza)
package abstractFactory.Pizza;
//具体披萨原料,对应的原料工厂:ChicagoPizzaIngredientFactory
public class ThickCrustDough implements Dough {
	public String toString() {
		return "ThickCrust style extra thick crust dough";
	}
}
package abstractFactory.Pizza;
//具体披萨原料,对应的原料工厂:NYPizzaIngredientFactory
public class ThinCrustDough implements Dough {
	public String toString() {
		return "Thin Crust Dough";
	}
}
package abstractFactory.Pizza;
//具体披萨原料,对应原料工厂:ChicagoPizzaIngredientFactory
public class PlumTomatoSauce implements Sauce {
	public String toString() {
		return "Tomato sauce with plum tomatoes";
	}
}
package abstractFactory.Pizza;
//具体披萨原料,对应的原料工厂:NYPizzaIngredientFactory
public class MarinaraSauce implements Sauce {
	public String toString() {
		return "Marinara Sauce";
	}
}
package abstractFactory.Pizza;
//具体披萨原料,对应原料工厂ChicagoPizzaIngredientFactory
public class MozzarellaCheese implements Cheese {
	public String toString() {
		return "Shredded Mozzarella";
	}
}
package abstractFactory.Pizza;
//具体披萨原料,对应原料工厂NYPizzaIngredientFactory
public class ReggianoCheese implements Cheese {
	public String toString() {
		return "Reggiano Cheese";
	}
}
package abstractFactory.Pizza;
//具体披萨原料,对应的原料工厂:ChicagoPizzaIngredientFactory
public class FrozenClams implements Clams {
	public String toString() {
		return "Frozen Clams from Chesapeake Bay";
	}
}
package abstractFactory.Pizza;
//具体披萨原料,对应的原料工厂:NYPizzaIngredientFactory
public class FreshClams implements Clams {
	public String toString() {
		return "Fresh Clams from Long Island Sound";
	}
}
package abstractFactory.Pizza;
//具体披萨子类
public class CheesePizza extends Pizza {
	PizzaIngredientFactory ingredientFactory;
	public CheesePizza(PizzaIngredientFactory ingredientFactory) {
		this.ingredientFactory = ingredientFactory;
	}
	@Override
	void prepare() {
		// TODO Auto-generated method stub
		System.out.println("Preparing " + name);
		dough = ingredientFactory.createDough();
		sauce = ingredientFactory.createSauce();
		cheese = ingredientFactory.createCheese();
	}
}
package abstractFactory.Pizza;
//具体披萨子类
public class ClamPizza extends Pizza {
	PizzaIngredientFactory ingredientFactory;
	public ClamPizza(PizzaIngredientFactory ingredientFactory) {
		this.ingredientFactory = ingredientFactory;
	}
	@Override
	void prepare() {
		// TODO Auto-generated method stub
		System.out.println("Preparing " + name);
		dough = ingredientFactory.createDough();
		sauce = ingredientFactory.createSauce();
		cheese = ingredientFactory.createCheese();
	}
}
        2.5 main方法实现抽象工厂模式
package abstractFactory.Pizza;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		PizzaStore nyStore = new NYPizzaStore();
		PizzaStore chicagoStore = new ChicagoPizzaStore();
		//纽约子店点餐
		Pizza pizza = nyStore.orderPizza("cheese");
		System.out.println("Ethan ordered a " + pizza + "\n");
		//芝加哥子店点餐
		pizza = chicagoStore.orderPizza("cheese");
		System.out.println("Joel ordered a " + pizza + "\n");
		//纽约子店点餐
		pizza = nyStore.orderPizza("clam");
		System.out.println("Ethan ordered a " + pizza + "\n");
		//芝加哥子店点餐
		pizza = chicagoStore.orderPizza("clam");
		System.out.println("Joel ordered a " + pizza + "\n");
	}

}
        2.6 UML图

三、代码结构图

四、工厂方法模式与抽象工厂模式的总结

  • 所有的工厂都是用来封装对象的创建
  • 简单工厂:虽然不是真正的设计模式,但仍不失为一个简单的方法,可以将客户程序从具体类解耦;
  • 工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象;
  • 抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中;
  • 所有工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合;
  • 工厂方法允许类将实例化延迟到子类进行。
  • 抽象工厂创建相关的对象家族,而不需要依赖它们的具体类。

        UML图对比

        工厂是很有威力的技巧,帮助我们针对抽象编程,而不要针对具体类编程​​​​​​​

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

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

相关文章

Simba:Mamba 增强了 U-ShiftGCN,用于视频中的骨骼动作识别

Simba:Mamba 增强了 U-ShiftGCN,用于视频中的骨骼动作识别 摘要IntroductionRelated WorksMethodologyDown-sampling ShiftGCN Encoder Experiments & ResultsDatasets Simba: Mamba augmented U-ShiftGCN for Skeletal Action Recognition in Video…

通过vue完成表格数据的渲染展示和vue的生命周期及小结

案例 通过vue完成表格数据的渲染展示 把视图区展示的数据 死数据替换掉 从vue的数据模型中读取 展示在视图区 vue中的数据 模型是js中的自定义类型 形成的数组 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">&l…

NL2SQL进阶系列(1):DB-GPT-Hub、SQLcoder、Text2SQL开源应用实践详解

NL2SQL进阶系列(1)&#xff1a;DB-GPT-Hub、SQLcoder、Text2SQL开源应用实践详解 NL2SQL基础系列(1)&#xff1a;业界顶尖排行榜、权威测评数据集及LLM大模型&#xff08;Spider vs BIRD&#xff09;全面对比优劣分析[Text2SQL、Text2DSL] NL2SQL基础系列(2)&#xff1a;主流…

2024华中杯C题平面曲线重建思路

华中杯数学建模思路 光纤传感技术是伴随着光纤及光通信技术发展起来的一种新型传感器技 术。它是以光波为传感信号、光纤为传输载体来感知外界环境中的信号&#xff0c;其基本原理是当外界环境参数发生变化时&#xff0c;会引起光纤传感器中光波参量&#xff08;如波长、相位、…

IP-guard WebServer 权限绕过漏洞复现(QVD-2024-14103)

0x01 免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删…

全球排名前十的搜索引擎,你猜百度排名在第几位?bing稳居二位!

通常情况下&#xff0c;营销人员在争夺其在线业务的流量时会非常关注Google&#xff0c;无论是通过他们的网站&#xff0c;博客文章还是其他形式的内容。考虑到谷歌无疑是最受欢迎的搜索引擎&#xff0c;拥有超过85%的搜索市场份额&#xff0c;这是有道理的。 但这种受欢迎程度…

【Qt】Qt Hello World 程序

文章目录 1、Qt Hello World 程序1.1 使用按钮实现1.1.1 使用可视化方式实现 1.1.2 纯代码方式实现 label创建堆&#xff08;内存泄漏&#xff09;或者栈问题Qt基础类&#xff08;Qstring、Qvector、Qlist&#xff09;乱码问题零散知识 1、Qt Hello World 程序 1.1 使用按钮实…

【代码随想录】【动态规划】day48:打家劫舍

打家劫舍1 def rob(self, nums):""":type nums: List[int]:rtype: int"""# 分为两个情况&#xff0c;偷还是不偷&#xff0c;# dp[i]为考虑到第i个房间时的最大值if len(nums) 0: # 如果没有房屋&#xff0c;返回0return 0if len(nums) 1: #…

QoS流量整形

流量整形是一种带宽技术形式&#xff0c;它延迟某些类型的网络数据包的流动&#xff0c;以确保更高优先级应用程序的网络性能&#xff0c;它主要涉及调整数据传输速率&#xff0c;以确保网络资源以最佳容量得到利用。流量整形的目的是防止网络拥塞并提高网络的整体性能&#xf…

穿越物联网的迷雾:深入理解MQTT协议

目录标题 1、MQTT简介核心特性 2、MQTT的工作原理通信过程 3、MQTT的消息质量&#xff08;QoS&#xff09;4、安全机制5、实践应用环境准备示例项目发布者客户端订阅者客户端 6、最佳实践7、结论8、参考资料 在物联网&#xff08;IoT&#xff09;的海洋中&#xff0c;数据像水流…

【深度学习】Attention、Self-Attention、Multi-Head Attention

一、Attention 在CV领域&#xff0c;注意力机制通常分为通道注意力和空间注意力或者两者结合。 一张图像经backbone得到的特征通常包括多个通道&#xff0c;每个通道是一个像素矩阵&#xff0c;每个通道对任务的贡献不尽相同&#xff0c;单个通道的特征图中每个像素对任务的贡…

Ansible在macOS上的安装部署

一、安装 Ansible&#xff08;使用 Homebrew&#xff09; 安装 Homebrew&#xff08;如果尚未安装&#xff09;&#xff1a; /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"使用 Homebrew 安装 Ansible&#x…

Hive进阶(1)----HDFS写入数据流程(赋图助君理解)

HDFS写入数据流程 1.理论流程描述 HDFS&#xff08;Hadoop分布式文件系统&#xff09;的数据写入流程是一个复杂但高效的过程&#xff0c;可以分为以下8个步骤&#xff1a; 1、client(客户端)发起文件上传请求&#xff1b; 2、通过发送RPC请求与NameNode建立通讯。NameNode…

从100美元到1亿美元,探究传奇交易员GCR的交易心得及其持仓

有史以来最“伟大”的交易员GCR终于回归。2022年&#xff0c;GCR的资金从100美元涨至1亿美元&#xff0c;通过做空LUNA成为有史以来最赚钱的交易员。 GCR又名Giant Cassock Revival&#xff0c;或许是从FTX和Luna崩盘事件中获利最多的人&#xff0c;其净资产达到1亿美元后便“…

lv_micropython for ESP32/S2/S3/C3

由于官方的lv_micropython编译ESP32S3/S2/C3会报错&#xff0c;因为这些芯片的esp-idf底层重写了接口&#xff0c;参照网友提供的方法修改lv_bindings/driver/esp32里的文件&#xff0c;解决编译错误。 问题列举&#xff1a;Issues lvgl/lv_binding_micropython GitHub 一…

视觉信息保真度VIF算法详细介绍

来源 算法核心思想来源该篇论文A VISUAL INFORMATION FIDELITY APPROACH TO VIDEO QUALITY ASSESSMENT;是2005年的一篇高引用文章; 是一种全参考的视频图像评价算法;在奈飞开源的视频质量评价工具vmaf中将其作为一个判断维度,具体关于vmaf介绍可以参考视频质量评价工具vmaf…

安全开发实战(2)---域名反查IP

目录 安全开发专栏 前言 域名与ip的关系 域名反查ip的作用 1.2.1 One 1.2.2 Two 1.2.3 批量监测 ​总结 安全开发专栏 安全开发实战http://t.csdnimg.cn/25N7H 这步是比较关键的一步,一般进行cdn监测后,获取到真实ip地址后,或是域名时,然后进行域名反查IP地址,进行进…

机器学习笔记 - 使用 OpenCV 的结构化森林进行边缘检测

一、简述 边缘检测是计算机视觉领域中一项非常重要的任务。这是许多纯计算机视觉任务(例如轮廓检测)的第一步。即使涉及深度学习,较深层也首先学习识别边缘,然后再学习图像的复杂特征。所以,我们可以说边缘检测在计算机视觉领域非常重要。拥有良好且高效的图像边缘检测算法…

微信小程序实现美食检索功能

1、打开浏览器搜索&#xff1a;腾讯位置服务 2、注册一个账号&#xff0c;有账号的直接登陆就行 3、注册登陆成功后&#xff0c;点击控制台 4、进入控制台后点击我的应用——>创建应用 5、添加key,注意看注释 6、key添加成功后&#xff0c;开始分配额度&#xff08;配额&…

复合机器人在磁钢上下料中的应用及其优势分析

复合机器人是一种集成了移动机器人和工业机器人功能的设备&#xff0c;其独特之处在于拥有“手、脚、眼、脑”的综合能力&#xff0c;从而实现了更高的灵活性和操作效率。在磁钢上下料的应用场景中&#xff0c;复合机器人能够发挥显著的优势。 首先&#xff0c;复合机器人可以根…