设计模式之3种工厂模式

本文深入解析了工厂模式的三种形式:简单工厂、工厂方法和抽象工厂,通过生活中的例子进行阐述。简单工厂适用于单一产品类的生产,工厂方法允许不同子类创建同一类对象,抽象工厂则能生产不同类别的一系列产品。此外,文章提到了工厂模式在日志记录、数据库访问等场景的应用,并警告避免工厂模式与类名直接关联。同时,枚举类工厂的示例展示了如何使用枚举实现工厂模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

工厂模式

1. 三种工厂模式说明

1.1 三种工厂模式区分

菜鸟教程-评论区有对三种工厂模式的总结

一句话概括工厂模式

  • 简单工厂:一个工厂类,一个产品抽象类(用固定原理产生同理对象)
  • 工厂方法:多个工厂类,一个产品抽象类(用不同原理产生同类对象)
  • 抽象工厂:多个工厂类,多个产品抽象类(产生不同对象)

生活中的工厂模式

  • 简单工厂类:一个麦当劳店,可以生产多种汉堡。
  • 工厂方法类:一个麦当劳店,可以生产多种汉堡。一个肯德基店,也可以生产多种汉堡。
  • 抽象工厂类:百胜餐饮集团下有肯德基和百事公司,肯德基生产汉堡,百事公司生成百事可乐。

1.2 简单(静态)工厂模式

五分钟设计模式 - 02简单工厂

简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。它通常指创建某一个统一的父类下的某种子类的实例。

简单工厂模式定义了一个创建对象的类,由这来类来封装实例化对象的行为(代码)

在我们要大量的创建某种、某类或者某批对象时,就使用到简单工厂模式


简单工厂要求工厂需要了解所有产品的实现细节,当客户传入参数给工厂时,工厂才能实例化对应的产品对象。这也要求每当有新产品加入时必须要修改工厂类,违反了开闭原则。由此引出工厂模式


1.3 工厂模式

五分钟设计模式 - 03工厂模式

工厂模式中,工厂被抽象出来一个抽象类(或接口),而具体的实例化操作需要由子类实现,相当于子工厂。

这样做可以当产品类的实例化操作延迟到工厂子类中完成。由工厂子类来决定应该实例化哪一个具体实现类。

现在,如果你新增了一个产品,那么你不需要修改原有的工厂,但你需要新增一个新的工厂实现类,来负责对你新产品的生产。这样符合开闭原则。

在这里插入图片描述

这个模式在jdk中有多种应用,其中生产迭代器也运用到了工厂的思想:

Collection可以被视为抽象工厂类,LinkedList和ArrayList是其实现类,他们分别负责生产ListItr和Itr两个产品。而Iterator是这两个产品的父类。

在这里插入图片描述

1.4 抽象工厂模式

五分钟设计模式 - 04抽象工厂模式

抽象工厂使一个工厂不仅仅只能生产某一个大类的产品,它是多个工厂模式的父类抽象,是工厂模式的扩展。

工厂方法和抽象工厂的概念比较接近,两个模式没有特别大的区别,实际运用应该不用分那么清

从下图可以看出,抽象工厂仅仅只是让工厂可以生产不同类别的产品而已。

同时,这种模式也有简单工厂的毛病:新增一个产品体系的时候,需要对抽象工厂和子类进行修改,违反开闭原则

抽象工厂原理类图

1.5 静态工厂与抽象工厂

如果工厂只有固定的一个,那么就用静态工厂就行了,因为不需要多种实现,也就不需要使用对象和多态。

如果工厂有多种实现,分别使用了不同的创造对象的原理,那么就不应该使用静态工厂,而应该将工厂视为可替换的对象,使用抽象方法来约束多个工厂的实现的行为。而这个工厂的具体实现的选择应该由使用方给定(外部注入)


2. 应用

使用场景:

  1. 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方
  2. 数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
  3. 设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口。

3. 警醒

工厂模式要警惕和类名产生直接关联,最好不用通过class反射获取对象。

工厂模式是用来干什么的?它属于创建模式,是解决子类创建问题的。换句话来说,调用者在调用时,并不知道(并不关心)运行时需要创建的到底是哪一个对象(不知道类名)。如果直接传入一个类名,那为何不直接new一个对象?何必走工厂模式呢。


4. 枚举类工厂

public enum Factory {
    CIRCLE(new Circle(),"CIRCLE"),
    RECTANGLE(new Rectangle(),"RECTANGLE"),
    SQUARE(new Square(),"SQUARE");
    
    // 成员变量,省略set/get
    private Shape shape;  
    private String name;  
    
    // 普通方法  
    public static Shape getShape(String name) {  
        for (Factory c : Factory.values()) {  
            if (c.name == name) {  
                return c.shape;  
            }  
        }  
        return null;  
    } 
    // 构造方法  
    private Factory(Shape shape, String name) {  
        this.shape = shape;  
        this.name = name;  
    } 
}

/*使用枚举类*/
Factory.getShape("CIRCLE").draw();
Factory.getShape("RECTANGLE").draw();
Factory.getShape("SQUARE").draw();

出自菜鸟教程——工厂模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值