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

一、抽象工厂模式概述

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

  • 模式动机
    • 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 {@Overridepublic Dough createDough() {// TODO Auto-generated method stubreturn new ThickCrustDough();}@Overridepublic Sauce createSauce() {// TODO Auto-generated method stubreturn new PlumTomatoSauce();}@Overridepublic Cheese createCheese() {// TODO Auto-generated method stubreturn new MozzarellaCheese();}@Overridepublic Clams createClam() {// TODO Auto-generated method stubreturn new FrozenClams();}}
package abstractFactory.Pizza;
//纽约原料工厂
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {@Overridepublic Dough createDough() {// TODO Auto-generated method stubreturn new ThinCrustDough();}@Overridepublic Sauce createSauce() {// TODO Auto-generated method stubreturn new MarinaraSauce();}@Overridepublic Cheese createCheese() {// TODO Auto-generated method stubreturn new ReggianoCheese();}@Overridepublic Clams createClam() {// TODO Auto-generated method stubreturn new FreshClams();}}
package abstractFactory.Pizza;
//具体披萨分店:芝加哥分店
public class ChicagoPizzaStore extends PizzaStore {@Overrideprotected Pizza createPizza(String item) {// TODO Auto-generated method stubPizza 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 {@Overrideprotected Pizza createPizza(String item) {// TODO Auto-generated method stubPizza 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;}@Overridevoid prepare() {// TODO Auto-generated method stubSystem.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;}@Overridevoid prepare() {// TODO Auto-generated method stubSystem.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 stubPizzaStore 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.mzph.cn/diannao/308.shtml

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

相关文章

41、二叉树-二叉树的层序遍历

思路: 层序遍历就是从左到右依次遍历。这个时候就可以使用队列的方式。例如先把头节点入队,然后遍历开始,首先计算队列长度,第一层,长度为了,遍历一次,依次出队,头结点出队&#xff…

Tomcat和Spring Boot配置https

生成测试证书 生成证书前,先验证本地是否正确配置jdk环境变量,如果jdk环境变量配置正确,在命令行程序输入生成证书的命令。 keytool -genkey -alias tomcat -keyalg RSA -keystore "F:\job\apache-tomcat-8.5.29\key\freeHttps.keysto…

微信小程序之图片上传并保存在服务器

先将图片上传到服务器,后端接口将保存好的图片地址返回给小程序,再将小程序中添加图像的图片的url替换为服务器中照片的存储地址(使微信小程序中显示出上传的图片)。 1、效果如下: 点击图像后选择图像: 结…

搜维尔科技:【工业仿真】煤矿机械安全事故VR警示教育系统

产品概述 搜维尔科技 煤矿机械安全事故VR警示教育系统 系统内容: 系统采用虚拟现实技术模拟矿井井下机械安全技术及事故,展现井下常见机械伤害事故,表现伤害事故的隐患点,能够模拟事故发生和发展过程;营造井下灾害发…

如何使用 Node.js 发送电子邮件全解和相关工具推荐

大多数Web应用程序都需要发送电子邮件。它可能用于注册、密码重置、状态报告,甚至是完整的市场营销活动,如新闻和促销。本教程解释了如何在Node.js中发送电子邮件,但其概念和挑战适用于您正在使用的任何系统。 你会在 npm 上找到大量与电子邮…

详细UI色彩搭配方案分享

UI 配色是设计一个成功的用户界面的关键之一。UI 配色需要考虑品牌标志、用户感受、应用程序的使用场景,这样可以帮助你创建一个有吸引力、易于使用的应用程序。本文将分享 UI 配色的相关知识,帮助设计师快速构建 UI 配色方案,以满足企业的需…

windows10小皮安装不同版本composer,实现自由切换使用

1、使用phpstudy小皮面板安装composer1.8.5和composer2.5.8两个版本; 2、打开刚才安装的composer安装目录:D:\phpstudy_pro\Extensions 3、打开composer1.8.5版本,修改composer.bat名称为composer1.8.5.bat: 4、打开composer2.5.8…

【机器学习300问】75、如何理解深度学习中Dropout正则化技术?

一、Dropout正则化的原理是什么? Dropout(随机失活)正则化是一种用于减少神经网络中过拟合现象的技术。Dropout正则化的做法是: 在训练过程中的每次迭代中,随机将网络中的一部分权重临时"丢弃"(即…

前端三大件速成 01 HTML

文章目录 一、前端基础知识二、标签1、什么是标签2、标签的属性3、常用标签(1)声明(2)注释(3)html 根标签(3)head标签(4)body标签 三、特殊字符四、其他标签1…

web安全学习笔记(11)

记一下第十五节课的内容。 一、创建MySQL执行函数 我们在function.php中,自定义一个函数: #SQL查询函数 function Qurey($sql) {#连接数据库$db new mysqli(172.20.10.3, liuyan, 123456, liuyan, 3306);#判断是否连接成功if (mysqli_connect_errno(…

redis的数据结构报错

文章目录 redis的数据结构报错Redis使用LocalDateTime报错问题 redis的数据结构报错 Redis使用LocalDateTime报错问题 SpringBoot整合Redis时,使用LocalDate以下报错 org.springframework.data.redis.serializer.SerializationException: Could not read JSON: C…

(八)Pandas窗口数据与数据读写 学习简要笔记 #Python #CDA学习打卡

一. 窗口数据(Window Functions) Pandas提供了窗口函数(Window Functions)用于在数据上执行滑动窗口操作,可以对数据进行滚动计算、滑动统计等操作。需要注意的是,在使用窗口函数时,需要根据实际需求选择合适的窗口大小和窗口函数&#xff0…

大数据------额外插件及技术------Git(完整知识点汇总)

Git 定义 它是分布式版本控制工具,主要用于管理开发过程中的源代码文件(如:Java类、xml文件、html页面等),在软件开发过程中被广泛应用 作用 代码回溯:快速回到某一代码历史版本版本切换:同一个…

【嵌入式开发】SecureCRTPortable工具进行串口信息监听打印

SecureCRTPortable工具进行串口信息监听打印 一、什么是SecureCRT二、如何使用SecureCRT进行串口监听1、硬件连接2、驱动安装3、软件连接4、串口连接5、日志设置 近期发现许多小伙伴欠缺SSH工具使用基础,工欲善其事,必先利其器,这里奉上使用教…

股票战法课程之主力的痕迹

文章目录 1. 主力的操作痕迹2. 主力的建仓2.1 建仓的三种方式2.2 建仓的五个特点2.3 建仓的迹象2.4 建仓的成交量特征 1. 主力的操作痕迹 序号痕迹原因1不跟随大盘节奏筹码都在主力手中2突发利空消息,股价不跌反涨主力被套,不希望散户抛盘3很小的成交量…

【Spring】Spring MVC入门

Spring MVC入门 一、什么是Spring Web MVC? 1.1 MVC定义 MVC是Model View Controller的缩写,是一种软件架构的设计模式,将软件系统分为模型、视图、控制器三个部分。 示意图如下: 可以看到,Controller作为一个“粘合剂”处于M…

Go 单元测试之mock接口测试

文章目录 一、gomock 工具介绍二、安装三、使用3.1 指定三个参数3.2 使用命令为接口生成 mock 实现3.3 使用make 命令封装处理mock 四、接口单元测试步骤三、小黄书Service层单元测试四、flags五、打桩(stub)参数 六、总结6.1 测试用例定义6.2 设计测试用…

详细分析Mysql常用函数(附Demo)

目录 前言1. 聚合函数2. 字符串函数3. 日期函数4. 条件函数5. 数值函数6. 类型转换函数 前言 由于实战中经常运用,索性来一个总结文 创建一个名为 employees 的表,包含以下字段: employee_id:员工ID,整数类型 first…

Linux的图形资源及指令

一、火车 1.切换到超级用户 su 2.下载资源 yum install -y sl 3.输入指令 sl,得到火车图形 如果没有得到该图形,就将2处改为yum install -y epel-release。 二、Linux的logo 1.在超级用户模式下下载资源 yum install -y linux_logo 2.输…

物联网(iot)深度解析——FMEA软件

物联网即IoT,是指通过各种信息传感器、射频识别技术、全球定位系统、红外感应器、激光扫描器等各种装置与技术,实时采集任何需要监控、连接、互动的物体或过程,采集其声、光、热、电、力学、化学、生物、位置等各种需要的信息,通过…