【设计模式】工厂模式(Factory Pattern)

本文介绍了工厂模式的三种形式:简单工厂、工厂方法和抽象工厂。通过物流管理系统和图形绘制的例子,阐述了如何运用这些模式。强调了在代码扩展性和资源复用方面的优势,同时也指出了增加子类可能导致的复杂性。最后,提到了工厂模式与简单工厂模式的区别,并提供了实现步骤和优缺点。

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

在这里插入图片描述

 

🔥 核心

一个工厂能够根据需要产生不同的产品。

如果是根据参数生产产品,则称为简单工厂模式;定义一个创建对象的工厂接口,其子类自己已经决定好了生产哪一种产品,则称为工厂模式;这个子类工厂能生产一套产品。则称为抽象工厂模式。

 

🙁 问题场景

还记得吗,在上一篇文章里,你开放了一款物流管理系统。

由于这款应用极其受欢迎,陆地运输公司、海路运输公司、航空运输公司都想要与你合作。

于是,你创建了一个运输工厂,工厂根据不同的订单,生产并开始一个个 卡车运输轮船运输飞机运输

这时,突然有人站出来,说这压根不是严格定义的工厂模式…

 

🙂 解决方案

这叫作简单工厂模式,并不是严格的工厂模式

你现在的运输工厂,是根据不同的订单在进行生产,订单即传入的参数。而如果是严格定义的工厂模式,你应该将这个 运输工厂 视为抽象,再创立若干个子工厂—— 卡车运输工厂轮船运输工厂飞机运输工厂 ,每个工厂完成自己固定的工作。

这时,太空公司又打来了电话。

你又从容的按下了接听键。因为你知道,物流管理系统的代码几乎不需要什么大费周章的扩展,你只需要再创立一个 火箭运输工厂 即可!

 

🌈 有趣的例子

圆形(Circle)正方形(Square)三角形(Triangle) 均实现了 图形(Shape) 接口,它们是三种产品。

图形工厂(ShapeFactory) 是一个接口,它有三个子类 圆形工厂(CircleFactory)正方形工厂(SquareFactory)三角形工厂(TriangleFactory) ,它们分别可以生产出自己固定的产品。
在这里插入图片描述

 三种图形的接口
interface Shape {
    void draw();
}

 圆形
class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("我是一个圆形,我正在画出自己 >_<");
    }
}

 正方形
class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("我是一个正方形,我正在画出自己 >_<");
    }
}

 三角形
class Triangle implements Shape {
    @Override
    public void draw() {
        System.out.println("我是一个三角形,我正在画出自己 >_<");
    }
}


 图形工厂接口
interface ShapeFactory {
    Shape getShape();
}

 圆形工厂
class CircleFactory implements ShapeFactory {
    @Override
    public Shape getShape() {
        return new Circle();
    }
}

 正方形工厂
class SquareFactory implements ShapeFactory {
    @Override
    public Shape getShape() {
        return new Square();
    }
}

 三角形工厂
class TriangleFactory implements ShapeFactory {
    @Override
    public Shape getShape() {
        return new Triangle();
    }
}
public class FactoryPatternDemo {
    public static void main(String[] args) {

        // 创建一个圆形工厂
        ShapeFactory circleFactory = new CircleFactory();
        // 获取圆形
        Shape circle1 = circleFactory.getShape();
        Shape circle2 = circleFactory.getShape();
        Shape circle3 = circleFactory.getShape();

		// 创建一个正方形工厂
        ShapeFactory squareFactory = new SquareFactory();
        // 获取圆形
        Shape square1 = squareFactory.getShape();
        Shape square2 = squareFactory.getShape();
        Shape square3 = squareFactory.getShape();

        // 创建一个三角形工厂
        ShapeFactory triangleFactory = new TriangleFactory();
        // 获取圆形
        Shape triangle1 = triangleFactory.getShape();
        Shape triangle2 = triangleFactory.getShape();
        Shape triangle3 = triangleFactory.getShape();

        // 试一试能不能用
        new CircleFactory().getShape().draw();
        new SquareFactory().getShape().draw();
        new TriangleFactory().getShape().draw();
        
    }
}
我是一个圆形,我正在画出自己 >_<
我是一个正方形,我正在画出自己 >_<
我是一个三角形,我正在画出自己 >_<

 

☘️ 使用场景

◾️当你在编写代码的过程中,如果无法预知对象确切类别及其依赖关系时,可使用工厂方法。

工厂方法将创建产品的代码与实际使用产品的代码分离,从而能在不影响其他代码的情况下扩展产品创建部分代码。

例如, 如果需要向应用中添加一种新产品,你只需要开发新的创建者子类,然后修改工厂方法即可。

◾️如果你希望用户能扩展你软件库或框架的内部组件,可使用工厂方法。

继承可能是扩展软件库或框架默认行为的最简单方法。但是当你使用子类替代标准组件时,框架如何辨识出该子类?

解决方案是将各框架中构造组件的代码集中到单个工厂方法中,并在继承该组件之外允许任何人对该方法进行重写。

让我们看看具体是如何实现的。假设你使用开源 UI 框架编写自己的应用。你希望在应用中使用圆形按钮,但是原框架仅支持矩形按钮。 你可以使用 圆形按钮(Round­Button) 子类来继承标准的 按钮(Button) 类。 但是,你需要告诉 UI框架(UIFramework) 类使用新的子类按钮代替默认按钮。

为了实现这个功能,你可以根据基础框架类开发子类 圆形按钮UI(UIWith­Round­Buttons) ,并且重写其 创建按钮(create­Button) 方法。基类中的该方法返回 按钮 对象,而你开发的子类返回 圆形按钮 对象。 现在,你就可以使用 圆形按钮UI类 代替 UI框架类 。就是这么简单!

◾️如果你希望复用现有对象来节省系统资源,而不是每次都重新创建对象,可使用工厂方法。

在处理大型资源密集型对象(比如数据库连接、文件系统和网络资源)时,你会经常碰到这种资源需求。

让我们思考复用现有对象的方法:

1)首先,你需要创建存储空间来存放所有已经创建的对象。
2)当他人请求一个对象时,程序将在对象池中搜索可用对象。
3)…然后将其返回给客户端代码。
4)如果没有可用对象,程序则创建一个新对象(并将其添加到对象池中)。

这些代码可不少!而且它们必须位于同一处,这样才能确保重复代码不会污染程序。

可能最显而易见,也是最方便的方式,就是将这些代码放置在我们试图重用的对象类的构造函数中。但是从定义上来讲,构造函数始终返回的是新对象,其无法返回现有实例。

因此,你需要有一个既能够创建新对象,又可以重用现有对象的普通方法。这听上去和工厂方法非常相像。

 

🧊 实现方式

(1)让所有产品都遵循同一接口。该接口必须声明对所有产品都有意义的方法。

(2)在工厂类中添加一个空的工厂方法。该方法的返回类型必须遵循通用的产品接口。

(3)在创建者代码中找到对于产品构造函数的所有引用。将它们依次替换为对于工厂方法的调用,同时将创建产品的代码移入工厂方法。

(4)现在,为工厂方法中的每种产品编写一个工厂子类,然后在子类中重写工厂方法,并将基本方法中的相关创建代码移动到工厂方法中。

(5)如果代码经过上述移动后,基础工厂方法中已经没有任何代码,你可以将其转变为抽象类。如果基础工厂方法中还有其他语句,你可以将其设置为该方法的默认行为。

 

🎲 优缺点

  ➕ 你可以避免创建者和具体产品之间的耦合。

  ➕ 单一职责原则。你可以将产品创建代码放在程序的单一位置,从而使得代码更容易维护。

  ➕ 开闭原则。无需更改现有客户端代码,你就可以在程序中引入新的产品类型。

  ➖ 应用工厂模式需要引入许多新的子类,代码可能会变得非常复杂。

 

🌸 补充

 简单工厂模式和工厂模式,最好加以区分,不要混淆哦!

 

🔗 参考网站

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值