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

embedded/2024/10/18 18:15:57/

一、抽象工厂模式概述

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

  • 模式动机
    • 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/embedded/8973.html

相关文章

Linux常见指令

目录 ls pwd whoami cd clear touch mkdir rmdir rm man cp mv cat tac more less head tail find which alias adduser passwd userdel su nano cat file uname shutdown |管道 echo > >> < stat date 持续更新 周边…

ThingsBoard通过规则链使用邮件发送报警信息

1、描述 2、通过规则链路配置发送邮件只需 两步 3、案例 1、基础链路 2、选择变换节点里面的To Email 3、 编辑节点to email 4、 将创建告警与to email链接 5、选择外部节点中的send email 6、配置邮箱相关信息&#xff0c;如过不知道密钥如何获取的&#xff0c;请查看下…

STM32 CAN的验收筛选器

STM32 CAN的验收筛选器 简介 CAN外设的验收筛选器&#xff0c;一共有28个筛选器组&#xff0c;每个筛选器组有2个寄存器&#xff0c; CAN1和CAN2共用的筛选器的。 在 CAN 协议中&#xff0c;消息的标识符与节点地址无关&#xff0c;但与消息内容有关。因此&#xff0c;发送节…

【QT学习】8.qt事件处理机制,事件过滤器,自定义事件

1.qt事件处理机制 事件处理&#xff1a; 当用户移动鼠标的时候 &#xff0c;创建一个 鼠标移动事件对象 然后把这个对象放到 事件队列里面去&#xff0c;事件管理器 从队列中 取出事件&#xff0c;然后 调用其对应的事件处理函数。 多态机制&#xff1a; &#x…

Android中的Zygote进程介绍

在Android系统中&#xff0c;Zygote是一个特殊的进程&#xff0c;主要负责孵化&#xff08;fork&#xff09;新的应用进程&#xff0c;从而加速应用的启动过程。Zygote进程是系统启动过程中创建的第一个进程&#xff0c;它会在系统启动时被初始化并一直运行在后台。 以下是Zyg…

信息流广告大行其是,微博回望“原生”的初心

摘要&#xff1a;有流量的地方&#xff0c;就当有原生信息流广告 信息流广告&#xff0c;自2006年Facebook推出后就迅速火遍全球数字营销界&#xff0c;被誉为实现了广告主、用户、媒体平台三赢。特别是随着OCPM/OCPX大放异彩&#xff0c;信息流广告几乎成为广告主的必选项&…

typora的基本使用方法

typora的基本使用方法 这是一份秘籍 markdown语法官方 快捷键和基本使用技巧 1.标题级数 快捷键&#xff1a;Ctrl 1~6 一级标题&#xff1a;Ctrl1 相同形式&#xff1a; #空格内容 第二种跳转 使用id名字 二级标题&#xff1a;Ctrl2 相同形式&#xff1a;##空格内容 以此…

网络协议——OSPF(开放式最短路径优先)详解

1.什么是OSPF 开放式最短路径优先OSPF 是一种动态的高度可靠和高度可扩展的路由协议&#xff0c;用于构建大型网络中的动态路由系统 2. OSPF的协议号为&#xff1a;89 3. OSPF的特点: OSPF是链路状态协议使用了区域概念&#xff1a;减少路由选择协议对路由器CPU&#xff0c;…