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

server/2024/9/23 22:32:32/

一、抽象工厂模式概述

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

  • 模式动机
    • 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.ppmy.cn/server/2881.html

相关文章

吴恩达机器学习:均值聚类法(K-means Clustering)

在本练习中,您将实现K-means算法并将其用于图像压缩。 您将从一个样本数据集开始,该数据集将帮助您直观地了解K-means算法的工作原理。之后,您将使用K-means算法进行图像压缩,将图像中出现的颜色数量减少到该图像中最常见的颜色。…

Spring IoC详解

1.Ioc容器的作用 在传统的编程方式中,对象之间的依赖关系往往通过直接调用其他对象的构造函数或方法来建立(即通过new对象的形式),这导致了代码之间的紧密耦合。这就如同一个齿轮组,它拥有多个独立的齿轮,…

天空盒1-天空盒的实现原理

天空盒是一种常用的实时渲染技术,用于在三维场景中模拟远处环境,例如天空、山脉或城市等。它通过将一个立方体贴图(也称为环境贴图)投影到场景的背景中,给人一种无限远的感觉。以下是天空盒的实现原理: 创建…

ExpressLRS硬件实测性能分析

ExpressLRS硬件实测性能分析 1. 源由2. 远航测试3. 实验室测试3.1 芯片RSSI与实测功率差异3.2 SNR信噪比稳定3.3 140db衰减器衰减,40个频点信号稳定 4. 外场测试4.1 无屏蔽样品4.2 有屏蔽样品4.3 有屏蔽vs无屏蔽样品 5. 估算6. 总结7. 补充说明 -- 50mW视频 1. 源由…

VUE中如何使用 JavaScript 变量来设置CSS变量,从而修改CSS属性 --color 的值

// Vue 组件&#xff08;组件名称&#xff1a;DataView&#xff09; <template><div :style"{ --mycolor: color }">这是一个带有自定义颜色的元素</div> </template><script setup lang"ts">const props defineProps({ tit…

Zabbix

目录 什么是 Zabbix&#xff1f; 主要组成部分 1. Zabbix Server 2. Zabbix Agent 3. Zabbix Proxy 4. Zabbix Web Interface 5. Zabbix Database Zabbix 的功能特点 1. 多种监控方式 2. 高度可定制性 3. 自动发现和配置 4. 告警和通知 5. 数据可视化和报告 6. 安…

2024年都江堰市农民合作社和家庭农场申报主体条件、入库程序要求

一、项目建设内容 项目建设要结合“天府粮仓”,充分挖掘地种水肥药机各要素,耕种管收各环节的增产潜力为重点,推广应用优良品种、农机农艺融合、集约高效生产等先进技术。 (一)农民合作社 支持示范社改善生产经营条件,应用先进技术,开展农产品质量认证,构建营销体系和建设清…

mysql 查询实战3-解答

对mysql 查询实战3-题目&#xff0c;进行一个解答 11、查询每⽉产品交易与退款情况 目标&#xff1a;查询每⽉产品交易&#xff08;交易总额&#xff0c;交易数&#xff09;与退款情况&#xff08;退款总额&#xff0c;退款数&#xff09; 1&#xff0c;先把日期格式化 使用 E…