当前位置:首页 > 科技 >

通俗理解工厂模式(工厂模式三种详解)

来源:原点资讯(www.yd166.com)时间:2024-07-04 04:55:24作者:YD166手机阅读>>

核心作用

定义一个用于创建产品的接口,由子类决定生产什么产品。

分类
  1. 简单工厂模式
  2. 工厂方法模式
  3. 抽象工厂模式
简单工厂模式

简单工厂模式是有一个工厂对象决定创建出哪一种产品类的实例。即定义了一个创建对象的类,由这个类来封装实例化对象的行为。

简单工厂有两种模式:

  1. 普通简单工厂模式;
  2. 静态简单工厂模式;
简单工厂模式的主要角色
  • 抽象产品:定义了产品的规范,描述了产品的主要特征和功能;
  • 具体产品:实现或者继承抽象产品的子类;
  • 具体工厂:提供了创建产品的方法,调用者通过该方法创建产品;
优势劣势

● 简单工厂模式,通过接收的参数不同来返回不同的对象实例;
● 对于增加新产品(新功能)无能为力!不修改代码的话,是无法扩展的。不满足开闭原则。

简单工厂模式的实现

抽象类Pizza

package top.simba1949.factory.simple.pizza; import lombok.Data; import lombok.extern.slf4j.Slf4j; /** * @author anthony * @datetime 2020/5/9 11:45 */ @Slf4j @Data public abstract class Pizza { protected String name; /** * 准备原材料,每种 Pizza 原材料不一致 */ public abstract void prepare(); /** * Pizza 烘烤 */ public void bake() { log.info("{} : baking", name); } /** * Pizza 切割 */ public void cut() { log.info("{} : cutting", name); } /** * Pizza 打包 */ public void box() { log.info("{} : boxing", name); } }

抽象类Pizza的实现

package top.simba1949.factory.simple.pizza; import lombok.extern.slf4j.Slf4j; /** * @author anthony * @datetime 2020/5/9 11:51 */ @Slf4j public class CheesePizza extends Pizza { @Override public void prepare() { log.info("芝士Pizza原材料准备中。。。"); } }

package top.simba1949.factory.simple.pizza; import lombok.extern.slf4j.Slf4j; /** * @author anthony * @datetime 2020/5/9 11:52 */ @Slf4j public class GreekPizza extends Pizza { @Override public void prepare() { log.info("希腊风味Pizza原材料准备中。。。"); } }

简单工厂(静态)

package top.simba1949.factory.simple.staticFacotry; import top.simba1949.factory.simple.pizza.CheesePizza; import top.simba1949.factory.simple.pizza.GreekPizza; import top.simba1949.factory.simple.pizza.Pizza; /** * @author anthony * @datetime 2020/5/9 12:51 */ public class SimpleFactoryByStatic { public static Pizza orderPizza(String type) { Pizza pizza = null; if ("cheese".equalsIgnoreCase(type)) { pizza = new CheesePizza(); pizza.setName("cheese"); } else if ("greek".equalsIgnoreCase(type)) { pizza = new GreekPizza(); pizza.setName("greek"); } if (null != pizza){ pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } return pizza; } }

简单工厂模式(普通)

package top.simba1949.factory.simple.commonFactory; import top.simba1949.factory.simple.pizza.CheesePizza; import top.simba1949.factory.simple.pizza.GreekPizza; import top.simba1949.factory.simple.pizza.Pizza; /** * @author anthony * @datetime 2023/7/15 13:19 */ public class SimpleFactoryByCommon { public Pizza orderPizza(String type) { Pizza pizza = null; if ("cheese".equalsIgnoreCase(type)) { pizza = new CheesePizza(); pizza.setName("cheese"); } else if ("greek".equalsIgnoreCase(type)) { pizza = new GreekPizza(); pizza.setName("greek"); } if (null != pizza){ pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } return pizza; } }

测试类

package top.simba1949.factory.simple; import lombok.extern.slf4j.Slf4j; import top.simba1949.factory.simple.commonFactory.SimpleFactoryByCommon; import top.simba1949.factory.simple.pizza.Pizza; import top.simba1949.factory.simple.staticFacotry.SimpleFactoryByStatic; /** * @author anthony * @datetime 2020/5/9 13:50 */ @Slf4j public class SimpleFactoryApplication { public static void main(String[] args) { String pizzaType = "cheese"; // 简单工厂(静态)模式 // simpleFactoryByStatic(pizzaType); // 简单工厂(普通)模式 simpleFactoryByCommon(pizzaType); } public static void simpleFactoryByStatic(String pizzaType){ // 用户订购 Pizza Pizza pizza = SimpleFactoryByStatic.orderPizza(pizzaType); // 得到 Pizza log.info("简单工厂(静态):订购的披萨是{}", pizza); } public static void simpleFactoryByCommon(String pizzaType){ SimpleFactoryByCommon simpleFactoryByCommon = new SimpleFactoryByCommon(); // 用户订购 Pizza Pizza pizza = simpleFactoryByCommon.orderPizza(pizzaType); // 得到 Pizza log.info("简单工厂(普通):订购的披萨是{}", pizza); } }工厂方法模式

工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。
工程方法模式将对象的实例化推迟到子类实例化。

工厂方法模式的主要角色
  • 抽象工厂:提供了创建产品的接口,调用者通过它访问到具体工厂的工厂方法来创建产品;
  • 具体工厂:主要是实现抽象工厂的抽象方法,完成具体产品的创建;
  • 抽象产品:定义了产品的规范,描述了产品的主要特征和功能;
  • 具体产品:实现类抽象产品所定义的接口,有具体工厂来创建,它同具体工厂一一对应;
工厂方法模式优缺点

优点

  • 用户只需要知道具体工厂的名称就可以得到所要的产品,无需知道产品的具体创建过程;
  • 在系统增加新产品时只需要添加具体产品类和对应的具体工厂类,无需对原工厂进行任何修改,满足开闭原则。

缺点

  • 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类增加了系统的复杂化度。产生类爆炸;
工厂方法模式的实现

UML 类图描述

通俗理解工厂模式,工厂模式三种详解(1)


咖啡类

package top.simba1949.factory.method.coffee; import lombok.Data; import lombok.extern.slf4j.Slf4j; /** * @author anthony * @datetime 2023/7/15 13:46 */ @Slf4j @Data public abstract class Coffee { private String name; public void addMilk(){ log.info("{} 添加了牛奶", name); } public void addSugar(){ log.info("{} 添加了糖", name); } }

package top.simba1949.factory.method.coffee; /** * @author anthony * @datetime 2023/7/15 13:51 */ public class AmericanoCoffee extends Coffee { }

package top.simba1949.factory.method.coffee; import lombok.Data; import lombok.extern.slf4j.Slf4j; /** * @author anthony * @datetime 2023/7/15 13:53 */ @Slf4j @Data public class LatteCoffee extends Coffee { }

工厂类

package top.simba1949.factory.method.factory; import top.simba1949.factory.method.coffee.Coffee; /** * @author anthony * @datetime 2023/7/15 13:48 */ public abstract class CoffeeFactory { public abstract Coffee createCoffee(); }

package top.simba1949.factory.method.factory; import lombok.extern.slf4j.Slf4j; import top.simba1949.factory.method.coffee.AmericanoCoffee; import top.simba1949.factory.method.coffee.Coffee; /** * @author anthony * @datetime 2023/7/15 13:49 */ @Slf4j public class AmericanoCoffeeFactory extends CoffeeFactory { @Override public Coffee createCoffee() { Coffee coffee = new AmericanoCoffee(); coffee.setName("美式咖啡"); return coffee; } }

package top.simba1949.factory.method.factory; import lombok.extern.slf4j.Slf4j; import top.simba1949.factory.method.coffee.Coffee; import top.simba1949.factory.method.coffee.LatteCoffee; /** * @author anthony * @datetime 2023/7/15 13:49 */ @Slf4j public class LatteCoffeeFactory extends CoffeeFactory { @Override public Coffee createCoffee() { Coffee coffee = new LatteCoffee(); coffee.setName("拿铁咖啡"); return coffee; } }

咖啡店

package top.simba1949.factory.method; import lombok.Data; import lombok.extern.slf4j.Slf4j; import top.simba1949.factory.method.coffee.Coffee; import top.simba1949.factory.method.factory.CoffeeFactory; /** * @author anthony * @datetime 2023/7/15 13:52 */ @Slf4j @Data public class CoffeeStore { public CoffeeFactory coffeeFactory; public Coffee orderCoffee(){ // 这里创建对应的对象 Coffee coffee = coffeeFactory.createCoffee(); coffee.addMilk(); coffee.addSugar(); return coffee; } }

测试类

package top.simba1949.factory.method; import lombok.extern.slf4j.Slf4j; import top.simba1949.factory.method.coffee.Coffee; import top.simba1949.factory.method.factory.AmericanoCoffeeFactory; import top.simba1949.factory.method.factory.CoffeeFactory; /** * @author anthony * @datetime 2020/5/9 14:30 */ @Slf4j public class MethodFactoryApplication { public static void main(String[] args) { // 创建咖啡店对象 CoffeeStore coffeeStore = new CoffeeStore(); // 创建工厂对象 CoffeeFactory coffeeFactory = new AmericanoCoffeeFactory(); coffeeStore.setCoffeeFactory(coffeeFactory); // 订购咖啡 Coffee coffee = coffeeStore.orderCoffee(); log.info("订购的咖啡是:{}", coffee); } }抽象工厂模式

是一种为访问类提供一个创建一组相关或者相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同组的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂可生产多个等级的产品。

抽象工厂模式的主要角色
  • 抽象工厂:提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品;
  • 具体工厂:主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建;
  • 抽象产品:定义了产品的规范,描述了产品的主要特征和功能,抽象工厂模式有多个抽象产品;
  • 具体产品:实现了抽象产品角色所定义的接口,由具体工厂创建,它同具体工厂是多对一的关系;
抽象工厂模式的优缺点

优点

当一个产品族中的多个对象被设计成一起工作时,他能保证客户端始终只使用同一个产品族中的对象;

缺点

当产品族中需要新增一个新的产品,所有的工厂类都需要进行修改;

使用场景
  • 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
  • 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
  • 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。

如:输入法换皮肤,一整套一起换。生成不同操作系统的程序。

抽象工厂模式的实现

UML

通俗理解工厂模式,工厂模式三种详解(2)


甜点

package top.simba1949.factory.abs.dessert; import lombok.Data; import lombok.extern.slf4j.Slf4j; /** * @author anthony * @datetime 2023/7/15 14:25 */ @Slf4j @Data public abstract class Dessert { private String name; public void show() { log.info("正在展示的甜点是{}", name); } }

package top.simba1949.factory.abs.dessert; /** * 抹茶慕斯 * * @author anthony * @datetime 2023/7/15 14:28 */ public class MatchaMousseDessert extends Dessert{ }

package top.simba1949.factory.abs.dessert; /** * 提拉米苏 * * @author anthony * @datetime 2023/7/15 14:26 */ public class TiramisuDessert extends Dessert { }

咖啡

package top.simba1949.factory.abs.coffee; import lombok.Data; import lombok.extern.slf4j.Slf4j; /** * @author anthony * @datetime 2023/7/15 14:26 */ @Slf4j @Data public abstract class Coffee { private String name; public void addMilk(){ log.info("{} 添加了牛奶", name); } public void addSugar(){ log.info("{} 添加了糖", name); } }

package top.simba1949.factory.abs.factory; import lombok.extern.slf4j.Slf4j; import top.simba1949.factory.abs.coffee.AmericanoCoffee; import top.simba1949.factory.abs.coffee.Coffee; import top.simba1949.factory.abs.dessert.Dessert; import top.simba1949.factory.abs.dessert.MatchaMousseDessert; /** * @author anthony * @datetime 2023/7/15 14:32 */ @Slf4j public class AmericanFactory extends AbsFactory { @Override public Coffee createCoffee() { Coffee coffee = new AmericanoCoffee(); coffee.setName("美式咖啡"); coffee.addSugar(); return coffee; } @Override public Dessert createDessert() { Dessert dessert = new MatchaMousseDessert(); dessert.setName("抹茶慕斯"); return dessert; } }

package top.simba1949.factory.abs.factory; import lombok.extern.slf4j.Slf4j; import top.simba1949.factory.abs.coffee.Coffee; import top.simba1949.factory.abs.coffee.LatteCoffee; import top.simba1949.factory.abs.dessert.Dessert; import top.simba1949.factory.abs.dessert.TiramisuDessert; /** * @author anthony * @datetime 2023/7/15 14:32 */ @Slf4j public class ItalyFactory extends AbsFactory { @Override public Coffee createCoffee() { Coffee coffee = new LatteCoffee(); coffee.setName("拿铁咖啡"); coffee.addMilk(); return coffee; } @Override public Dessert createDessert() { Dessert dessert = new TiramisuDessert(); dessert.setName("提拉米苏"); return dessert; } }

工厂

package top.simba1949.factory.abs.factory; import top.simba1949.factory.abs.coffee.Coffee; import top.simba1949.factory.abs.dessert.Dessert; /** * @author anthony * @datetime 2023/7/15 14:31 */ public abstract class AbsFactory { public abstract Coffee createCoffee(); public abstract Dessert createDessert(); }

package top.simba1949.factory.abs.factory; import lombok.extern.slf4j.Slf4j; import top.simba1949.factory.abs.coffee.AmericanoCoffee; import top.simba1949.factory.abs.coffee.Coffee; import top.simba1949.factory.abs.dessert.Dessert; import top.simba1949.factory.abs.dessert.MatchaMousseDessert; /** * @author anthony * @datetime 2023/7/15 14:32 */ @Slf4j public class AmericanFactory extends AbsFactory { @Override public Coffee createCoffee() { Coffee coffee = new AmericanoCoffee(); coffee.setName("美式咖啡"); coffee.addSugar(); return coffee; } @Override public Dessert createDessert() { Dessert dessert = new MatchaMousseDessert(); dessert.setName("抹茶慕斯"); return dessert; } }

package top.simba1949.factory.abs.factory; import lombok.extern.slf4j.Slf4j; import top.simba1949.factory.abs.coffee.Coffee; import top.simba1949.factory.abs.coffee.LatteCoffee; import top.simba1949.factory.abs.dessert.Dessert; import top.simba1949.factory.abs.dessert.TiramisuDessert; /** * @author anthony * @datetime 2023/7/15 14:32 */ @Slf4j public class ItalyFactory extends AbsFactory { @Override public Coffee createCoffee() { Coffee coffee = new LatteCoffee(); coffee.setName("拿铁咖啡"); coffee.addMilk(); return coffee; } @Override public Dessert createDessert() { Dessert dessert = new TiramisuDessert(); dessert.setName("提拉米苏"); return dessert; } }

测试

package top.simba1949.factory.abs; import lombok.extern.slf4j.Slf4j; import top.simba1949.factory.abs.coffee.Coffee; import top.simba1949.factory.abs.dessert.Dessert; import top.simba1949.factory.abs.factory.ItalyFactory; /** * @author anthony * @datetime 2023/7/15 14:37 */ @Slf4j public class AbsFactoryApplication { public static void main(String[] args) { ItalyFactory italyFactory = new ItalyFactory(); Coffee coffee = italyFactory.createCoffee(); log.info("订购的咖啡是:{}", coffee); Dessert dessert = italyFactory.createDessert(); log.info("订购的甜品是:{}", dessert); } } JDK 源码中的工厂模式

Calendar instance = Calendar.getInstance(); public static Calendar getInstance() { return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT)); } private static Calendar createCalendar(TimeZone zone, Locale aLocale) { CalendarProvider provider = LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale).getCalendarProvider(); if (provider != null) { try { return provider.getInstance(zone, aLocale); } catch (IllegalArgumentException iae) { // fall back to the default instantiation } } // 根据不同的入参,返回不同的Calendar子类 Calendar cal = null; if (aLocale.hasExtensions()) { String caltype = aLocale.getUnicodeLocaleType("ca"); if (caltype != null) { switch (caltype) { case "buddhist": cal = new BuddhistCalendar(zone, aLocale); break; case "japanese": cal = new JapaneseImperialCalendar(zone, aLocale); break; case "gregory": cal = new GregorianCalendar(zone, aLocale); break; } } } if (cal == null) { // If no known calendar type is explicitly specified, // perform the traditional way to create a Calendar: // create a BuddhistCalendar for th_TH locale, // a JapaneseImperialCalendar for ja_JP_JP locale, or // a GregorianCalendar for any other locales. // NOTE: The language, country and variant strings are interned. if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") { cal = new BuddhistCalendar(zone, aLocale); } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja" && aLocale.getCountry() == "JP") { cal = new JapaneseImperialCalendar(zone, aLocale); } else { cal = new GregorianCalendar(zone, aLocale); } } return cal; },

栏目热文

工厂的生态模式(如何把濒临倒闭的工厂做起来)

工厂的生态模式(如何把濒临倒闭的工厂做起来)

齐鲁网·闪电新闻10月24日讯 建立健全绿色低碳循环发展经济体系,促进经济社会发展全面绿色转型,是解决我国资源环境生态问...

2024-07-04 04:58:48查看全文 >>

简单工厂模式的优势(工厂模式与工厂方法模式的区别)

简单工厂模式的优势(工厂模式与工厂方法模式的区别)

引言在软件设计中,工厂模式作为一种创建型设计模式,以其独特的设计理念和实现方式为系统架构带来了诸多优势。本文将详细介绍工...

2024-07-04 05:32:06查看全文 >>

简单工厂模式和工厂模式区别(工厂方法模式的通俗理解)

简单工厂模式和工厂模式区别(工厂方法模式的通俗理解)

简单工厂模式(Simple Factory Pattern)是一种创建型的设计模式,主要用于创建对象实例。在简单工厂设计...

2024-07-04 05:19:19查看全文 >>

羊奶适合每天喝吗(羊奶不建议长期喝吗)

羊奶适合每天喝吗(羊奶不建议长期喝吗)

羊奶要喝多少?喝少了难以发挥作用效果,喝多了难以吸收浪费了。需根据年龄阶段、工作强度来区分羊奶的用量。在正常的饮食下,每...

2024-07-04 05:28:21查看全文 >>

羊奶怎么能喝下去(羊奶为什么不建议喝)

羊奶怎么能喝下去(羊奶为什么不建议喝)

在早餐时间,很多人都有喝奶的习惯。以前说到奶,大多数人想到的是牛奶,而随着时代的进步和生活水平的提高,羊奶凭借高营养价值...

2024-07-04 05:06:46查看全文 >>

简单工厂模式和抽象工厂模式(设计模式深入浅出之工厂模式)

简单工厂模式和抽象工厂模式(设计模式深入浅出之工厂模式)

前面的22个常用的设计模式现已学习完毕,大家可以看到22个设计模式中提及到了带有“工厂”性质的相关模式,例如:构建方法...

2024-07-04 05:32:48查看全文 >>

工厂模式有哪些好处(工厂模式和简单工厂模式的区别)

工厂模式有哪些好处(工厂模式和简单工厂模式的区别)

在程序中类是表示客观世界存在的某类群体的一些基本特征的抽象,对象就是一个个具体的东西,也可以理解为类的一个具体实例。工厂...

2024-07-04 05:30:41查看全文 >>

广东旅游景点推荐一览表(广东十大旅游景点推荐表)

广东旅游景点推荐一览表(广东十大旅游景点推荐表)

广东,一个充满活力与故事的地方,不仅孕育了独特的岭南文化,接下来盘点下广东最值得去的十大景点,保证让你的行程充满趣味与欢...

2024-07-04 05:05:23查看全文 >>

广东旅游景点大全图(广东十大旅游景点分布图)

广东旅游景点大全图(广东十大旅游景点分布图)

千年商都、岭南文化中心、近现代革命重要起源地之一、食在广州......这些都是广州的标签深厚的历史积淀,多元的城市人群是...

2024-07-04 05:15:11查看全文 >>

西红柿牛腩煮得柴(西红柿炖牛腩怎么提前用电饭煲炖)

西红柿牛腩煮得柴(西红柿炖牛腩怎么提前用电饭煲炖)

做番茄牛腩时,很多人加错了水,难怪炖出来的牛腩发柴难嚼不入味。现在已经是秋天了,自古以来,在民间就有秋天“贴秋膘”的习俗...

2024-07-04 05:12:07查看全文 >>

文档排行