Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >设计模式(二、三):创建型之工厂方法模式和抽象工厂模式

设计模式(二、三):创建型之工厂方法模式和抽象工厂模式

作者头像
冬天vs不冷
发布于 2025-01-21 01:15:41
发布于 2025-01-21 01:15:41
13300
代码可运行
举报
文章被收录于专栏:springbootspringboot
运行总次数:0
代码可运行

一、设计模式分类

  • 创建型模式
    • 用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”
    • 提供了单例、原型、工厂方法、抽象工厂、建造者 5 种创建型模式
  • 结构型模式
    • 用于描述如何将类或对象按某种布局组成更大的结构
    • 提供了代理、适配器、桥接、装饰、外观、享元、组合 7 种结构型模式
  • 行为型模式
    • 用于描述类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务,以及怎样分配职责
    • 提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器 11 种行为型模式

二、概述

需求:设计一个咖啡店点餐系统

  • 设计一个咖啡类(Coffee)
  • 并定义其两个子类(美式咖啡【AmericanCoffee】和拿铁咖啡【LatteCoffee】)
  • 再设计一个咖啡店类(CoffeeStore),咖啡店具有点咖啡的功能
  • 具体类的设计如下:
  • 这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重
  • 假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则
  • 如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦
  • 如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的
  • 所以说,工厂模式最大的优点就是:解耦

三、简单工厂模式

  • 简单工厂不属于23种经典设计模式之一
  • 简单工厂不是一种设计模式,反而比较像是一种编程习惯

1、结构

简单工厂包含如下角色:

  • 抽象产品 :定义了产品的规范,描述了产品的主要特性和功能
  • 具体产品 :实现或者继承抽象产品的子类
  • 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品

2、实现

现在使用简单工厂对上面案例进行改进,类图如下:

工厂类代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class SimpleCoffeeFactory {
    public Coffee createCoffee(String type) {
        Coffee coffee = null;
        if("americano".equals(type)) {
            coffee = new AmericanoCoffee();
        } else if("latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        return coffee;
    }
}
  • 如果需要Coffee对象直接从SimpleCoffeeFactory工厂中获取即可
  • 这样也就解除了和Coffee实现类的耦合,同时又产生了新的耦合
    • CoffeeStore对象和SimpleCoffeeFactory工厂对象的耦合
    • 工厂对象和商品对象的耦合
  • 如果再加新品种的咖啡,我们势必要需求修改SimpleCoffeeFactory的代码,违反了开闭原则

3、扩展:静态工厂

  • 在开发中也有一部分人将工厂类中的创建对象的功能定义为静态的
  • 这个就是静态工厂模式,它也不是23种设计模式中的
  • 代码如下:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class SimpleCoffeeFactory {
    public static Coffee createCoffee(String type) {
        Coffee coffee = null;
        if("americano".equals(type)) {
            coffee = new AmericanoCoffee();
        } else if("latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        return coffe;
    }
}

四、工厂方法模式

  • 针对上例中的缺点,使用工厂方法模式就可以完美的解决,完全遵循开闭原则
  • 定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象
  • 工厂方法使一个产品类的实例化延迟到其工厂的子类

1、结构

工厂方法模式的主要角色:

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品
  • 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应

2、 实现

使用工厂方法模式对上例进行改进,类图如下:

抽象工厂:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface CoffeeFactory {
    //创建咖啡对象的方法
    Coffee createCoffee();
}

具体工厂:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 拿铁咖啡工厂,专门用来生产拿铁咖啡
public class LatteCoffeeFactory implements CoffeeFactory {
    @Override
    public Coffee createCoffee() {
        return new LatteCoffee();
    }
}

// 美式咖啡工厂对象,专门用来生产美式咖啡
public class AmericanCoffeeFactory implements CoffeeFactory {
    @Override
    public Coffee createCoffee() {
        return new AmericanCoffee();
    }
}

咖啡店类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class CoffeeStore {

    private CoffeeFactory factory;

    public void setFactory(CoffeeFactory factory) {
        this.factory = factory;
    }

    //点咖啡功能
    public Coffee orderCoffee() {
        Coffee coffee = factory.createCoffee();
        //加配料
        coffee.addMilk();
        coffee.addsugar();
        return coffee;
    }
}
  • 要增加产品类时也要相应地增加工厂类,不需要修改工厂类的代码了,这样就解决了简单工厂模式的缺点
  • 工厂方法模式是简单工厂模式的进一步抽象
  • 由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点

3、优缺点

优点

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

缺点

  • 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度

五、抽象工厂模式

  • 工厂方法模式中考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机
  • 工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品
  • 本节要介绍的抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族
  • 下图所示横轴是产品等级,也就是同一类产品
  • 纵轴是产品族,也就是同一品牌的产品,同一品牌的产品产自同一个工厂
  • 抽象工厂模式是工厂方法模式的升级版本
  • 工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品

1、结构

抽象工厂模式的主要角色如下:

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品
  • 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系

2、实现

  • 现咖啡店业务发生改变,不仅要生产咖啡还要生产甜点,如提拉米苏、抹茶慕斯等
  • 要是按照工厂方法模式,需要定义提拉米苏类、抹茶慕斯类、提拉米苏工厂、抹茶慕斯工厂、甜点工厂类,很容易发生类爆炸情况
  • 拿铁咖啡和提拉米苏是同一产品族(也就是都属于意大利风味)
  • 美式咖啡和抹茶慕斯是同一产品族(也就是都属于美式风味)
  • 使用抽象工厂模式实现。类图如下:

抽象工厂:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface DessertFactory {
    //生产咖啡的功能
    Coffee createCoffee();

    //生产甜品的功能
    Dessert createDessert();
}

具体工厂:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//美式甜点工厂-生产美式咖啡和抹茶慕斯
public class AmericanDessertFactory implements DessertFactory {
	@Override
    public Coffee createCoffee() {
        return new AmericanCoffee();
    }
	@Override
    public Dessert createDessert() {
        return new MatchaMousse();
    }
}
//意大利风味甜点工厂-生产拿铁咖啡和提拉米苏甜品
public class ItalyDessertFactory implements DessertFactory {
	@Override
    public Coffee createCoffee() {
        return new LatteCoffee();
    }
	@Override
    public Dessert createDessert() {
        return new Tiramisu();
    }
}

客户端:

  • Coffee和Dessert是抽象产品类
  • show(),抽象类中定义行为,具体实现交给子类
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Client {
    public static void main(String[] args) {
        //创建的是意大利风味甜品工厂对象
        //ItalyDessertFactory factory = new ItalyDessertFactory();
        AmericanDessertFactory factory = new AmericanDessertFactory();
        //获取拿铁咖啡和提拉米苏甜品
        Coffee coffee = factory.createCoffee();
        Dessert dessert = factory.createDessert();

        System.out.println(coffee.getName());
        dessert.show();
    }
}

如果要加同一个产品族的话,只需要再加一个对应的工厂类即可,不需要修改其他的类

3、优缺点

优点

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

缺点

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

六、JDK源码解析-Collection.iterator方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Demo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("令狐冲");
        list.add("风清扬");
        list.add("任我行");

        //获取迭代器对象
        Iterator<String> it = list.iterator();
        //使用迭代器遍历
        while(it.hasNext()) {
            String ele = it.next();
            System.out.println(ele);
        }
    }
}
  • 对上面的代码大家应该很熟,使用迭代器遍历集合,获取集合中的元素
  • 而单列集合获取迭代器的方法就使用到了工厂方法模式

通过类图看看结构:

  • Collection接口是抽象工厂类(声明Iterator iterator()方法)
  • ArrayList是具体的工厂类(new Itr()创建返回Iterator对象)
  • Iterator接口是抽象商品类(Itr实现Iterator接口类,是ArrayList内部类
  • ArrayList类中的Iter内部类是具体的商品(Itr是ArrayList内部类)
  • 在具体的工厂类中iterator()方法创建具体的商品类的对象
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-06-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java设计模式-工厂模式(3)抽象工厂模式
抽象工厂模式中存在四种角色,分别是抽象工厂角色,具体工厂角色,抽象产品角色,具体产品角色。
宁在春
2022/10/31
2880
Java设计模式-工厂模式(3)抽象工厂模式
02.工厂模式设计思想
本文档详细介绍了工厂模式设计思想,包括简单工厂、工厂方法和抽象工厂三种类型。简单工厂通过参数返回不同类的实例,适合对象较少的场景;工厂方法通过定义抽象工厂接口,由子类实现具体对象的创建,增强扩展性;抽象工厂则能创建多个产品族,适用于产品间有依赖关系的情况。文档还通过咖啡店点餐系统案例,展示了三种模式的应用及优缺点,帮助读者理解和选择合适的工厂模式。
杨充
2024/10/17
1090
Java设计模式-工厂模式(2)工厂方法模式
工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
宁在春
2022/10/31
4260
Java设计模式-工厂模式(2)工厂方法模式
Java设计模式---创建型模式
本章Java设计模式的创建型模式的介绍,是通过学习视频记录的笔记,欢迎留言指出错误点
用户11010370
2024/03/12
1360
一篇文章带你了解设计模式——创建者模式
下面我们来介绍第一种设计模式,创建型模式的主要关注点是怎样创建对象,它的主要特点是“将对象的创建与使用分离”。
秋落雨微凉
2023/03/08
7560
一篇文章带你了解设计模式——创建者模式
多种工厂模式的运用
在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则。如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:**解耦**。
忆愿
2024/08/02
980
多种工厂模式的运用
【设计模式】我这样学习设计模式-工厂模式
工厂模式是用来创建对象的一种最常用的设计模式。根据抽象程度的不同可以分为:简单工厂模式,工厂方法模式 和 抽象工厂模式。
一尾流莺
2022/12/10
5530
【设计模式】我这样学习设计模式-工厂模式
设计模式之工厂模式!深入解析简单工厂模式,工厂方法模式和抽象工厂模式
工厂模式 创建型模式: 对类的实例化过程进行抽象,能够将对象的创建和对象的使用分离开来 为了使得软件的结构更加清晰,外界对于这些对象使用只需要知道共同的接口,而不在意具体实现的细节,这样使得整个系统更加符合单一职责的原则 创建型模式隐藏了类的实例的创建细节,通过隐藏对象创建和组合过程从而使得整个系统相互独立的目的 创建型模式在创建什么,由谁创建,何时创建更加灵活 工厂模式是一个重要的创建型模式,主要功能就是实例化对象 工厂模式: 负责将有共同接口的类实例化 主要解决接口选择问题 在不同的条件下需要创建
攻城狮Chova
2022/03/24
4380
设计模式之工厂模式!深入解析简单工厂模式,工厂方法模式和抽象工厂模式
设计模式(6)——抽象工厂模式(Abstract Factory Pattern,创建型)
使用设计模式可以提高代码的可复用性、可扩充性和可维护性。抽象工厂模式(Abstract Factory Pattern)属于创建型模式,为创建一组相关或者相互依赖的对象(产品族)提供一个抽象类接口,而无需指定它们的具体类。。产品族的定义是:某个具体工厂生产的所有类型的产品,比如定义了一个抽象工厂接口A,它可以生产三种产品:p1、p2、p3,而这三个产品就叫一个产品族。
恋喵大鲤鱼
2018/08/03
4940
设计模式(6)——抽象工厂模式(Abstract Factory Pattern,创建型)
Java设计模式之工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)
在java中,创建一个对象最简单的方法就是使用new关键字。但在一些复杂的业务逻辑中,创建一个对象不只需要new一行代码就成了,可能需要一些列的初始化设置,或先创建一些辅助对象来创建这个对象。
用户2409797
2018/08/30
6600
创建型设计模式(4)—— 抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式(Abstract Factory Pattern)属于创建型模式,为创建一组相关或者相互依赖的对象(产品族)提供一个抽象类接口,而无需指定它们的具体类。 产品族的定义是:某个具体工厂生产所有类型的产品,比如定义了一个抽象工厂接口 A,它可以生产三种产品:p1、p2、p3,而这三个产品就叫一个产品族。
恋喵大鲤鱼
2024/05/24
1120
创建型设计模式(4)—— 抽象工厂模式(Abstract Factory Pattern)
【设计模式】抽象工厂模式
前面介绍的 工厂模式 中考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机、计算机软件学院只培养计算机软件专业的学生等。
Li_XiaoJin
2022/06/10
2580
【设计模式】抽象工厂模式
详解设计模式:抽象工厂模式
抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。这里的抽象角色就是产品族。
栗筝i
2022/12/02
3870
详解设计模式:抽象工厂模式
抽象工厂模式(Abstract Factory)- 最易懂的设计模式解析
在上文提到的最易懂的设计模式系列解析:工厂方法模式,发现工厂方法模式存在一个严重的问题:
Carson.Ho
2019/02/22
3.4K0
设计模式实战-抽象工厂模式,分而治之
继续上节,这回我们讲下抽象工厂模式,抽象工厂模式是工厂模式(简单工厂、工厂方法)中最具抽象和一般性的一种形态。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。
架构师修炼
2020/07/17
9300
设计模式之工厂方法和抽象工厂
全网最详细的工厂设计模式,本文主要是创建型设计模式中的工厂方法和抽象工厂,先由传统实现方式引出问题,接着对代码改进到简单工厂,后扩展到工厂方法,最后是抽象工厂模式,文中包括概念理解和相关实现代码。
程序员田同学
2022/07/28
2070
设计模式---工厂模式
简单工厂模式属于类的创新型模式,又叫静态工厂方法模式,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。
大忽悠爱学习
2021/11/15
3650
抽象工厂模式 创建型 设计模式(四)
所有的ConcreteCreator的返回类型都是Product,因为抽象工厂角色Creator就是返回Product 
noteless
2018/12/12
4380
JAVA设计模式之抽象工厂模式
前面已经介绍过简单工厂模式和工厂方法模式,这里继续介绍第三种工厂模式-抽象工厂模式,还是以汽车的制造为例。
秃头哥编程
2019/06/05
4170
JAVA设计模式之抽象工厂模式
Carson带你学设计模式:抽象工厂模式(Abstract Factory)
抽象工厂模式,即Abstract Factory Pattern,提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类;具体的工厂负责实现具体的产品实例。
Carson.Ho
2022/03/25
2980
Carson带你学设计模式:抽象工厂模式(Abstract Factory)
推荐阅读
相关推荐
Java设计模式-工厂模式(3)抽象工厂模式
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验