工厂方法模式

工厂方法 Factory Method

工厂方法模式是一种创建型设计模式,其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。

工厂模式分为:简单工厂、工厂方法、抽象工厂。


为什么要使用?

工厂方法模式的对象职责:

在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。 换句话说,父类只需要知道它能创建对象,具体什么是实例对象让子类去考虑。

例如在实际开发中,你需要用户能够去自定义组件,那么你就需要制定一套规则,让用户依照你的规则去开发。工厂方法模式🏭就是非常好的选择。它能够让创建产品和使用产品分离,那么用户就可以在不修改核心代码的同时,更改为自定义组件。

父类决定实例的生成方式,但并不决定所要生成的具体的类,具体的类全部交由子类去负责。这样就能让创建者和具体产品解耦。


模式结构

  • 产品 (Product) 将会对接口进行声明。 对于所有由创建者及其子类构建的对象, 这些接口都是通用的。
  • 具体产品 (Concrete Products) 是产品接口的不同实现。
  • 创建者 (Creator) 类声明返回产品对象的工厂方法。 该方法的返回对象类型必须与产品接口相匹配。注意, 并不一定每次调用工厂方法都会创建新的实例。 工厂方法也可以返回缓存、 对象池或其他来源的已有对象。
  • 具体创建者 (Concrete Creators) 将会重写基础工厂方法, 使其返回不同类型的产品。

工厂方法模式的类图:

Creator 类只需要知道 create() 方法可以创建出 Product,而不需要知道其他具体实现。

当我们更换实现为新的 ConcreteCreator 类时,那么 create() 方法创建的 ConcreteProduct 也会更改。如果 Creator 类中能够创建不同的 Product 时,它就离抽象工厂更近一步了。

工厂方法模式侧重于直接对具体产品的实现进行封装和调用,通过统一的接口定义来约束程序的对外行为。


模式实现

该示例使用工厂方法模式来构建 DialogButton 的关系,并提供了一套默认样式。该模式使得用户也可以自定义样式,只需要继承抽象类并实现。

示例程序的类图

在这里插入图片描述

代码实现
抽象创建者 Creator
package example.framework;

/** 抽象对话框 */
public abstract class Dialog {
    /** 显示对话框 */
    public void show() {
        Button button = createButton();
        button.render();
    }

    /**
     * 创建按键组件
     * @return 按键组件实例
     */
    public abstract Button createButton();
}
抽象产品 Product
package example.framework;

/** 抽象按键产品 */
public abstract class Button {
    /** 按键标签 */
    protected String label = "Button";

    /**
     * 展示按键
     */
    public abstract void render();
}
默认实现
package example.concrete;

import example.framework.Button;
import example.framework.Dialog;

/** 默认对话框实现 */
public class DefaultDialog extends Dialog {
    /**
     * 创建按键组件
     * @return 按键组件实例
     */
    @Override
    public Button createButton() {
        return new DefaultButton();
    }
}
package example.concrete;

import example.framework.Button;

/** 默认按键产品实现 */
public class DefaultButton extends Button {
    /** 展示按键 */
    @Override
    public void render() {
        System.out.println("| " + this.label + " |");
    }
}
自定义实现
package example.my;

import example.framework.Button;
import example.framework.Dialog;

/** 自定义对话框实现 */
public class MyDialog extends Dialog {
    /**
     * 创建按键组件
     * @return 按键组件实例
     */
    @Override
    public Button createButton() {
        return new MyButton();
    }
}
package example.my;

import example.framework.Button;

/** 自定义按键产品实现 */
public class MyButton extends Button {
    /** 展示按键 */
    @Override
    public void render() {
        System.out.println("( " + this.label + " )");
    }
}
代码测试
import example.concrete.DefaultDialog;
import example.framework.Dialog;
import example.my.MyDialog;

/** 测试工厂方法模式 */
public class Test {
    public static void main(String[] args) {
        Dialog defaultDialog = new DefaultDialog();
        defaultDialog.show();
        System.out.println("------------- 分割线 -------------");
        Dialog myDialog = new MyDialog();
        myDialog.show();
    }
}
输出结果
| Button |
------------- 分割线 -------------
( Button )

由上述可以看出,我们不需要去修改默认实现类就可以将样式替换成自定义的。


常用场景和解决方案

  • 有限、可重用的对象,使用工厂方法模式可以有效节约资源,例如:
    • 需要使用很多重复代码创建对象时,比如,DAO 层的数据对象、API 层的 VO 对象等。
    • 创建对象要访问外部信息或资源时,比如,读取数据库字段、获取访问授权 token 信息、配置文件等。
    • 创建需要统一管理生命周期的对象时,比如,会话信息、用户网页浏览轨迹对象等。
    • 创建池化对象时,比如,连接池对象、线程池对象、日志对象等。
  • 希望隐藏对象的真实类型时,比如,不希望使用者知道对象的真实构造函数参数等。
  • 不确定对象确切类别及其依赖关系时,可以使用工厂方法。工厂方法能让你在使用时不考虑它以后可能会拓展的具体实现。
  • 如果你希望用户能扩展你软件库或框架的内部组件,可使用工厂方法。

模式的优缺点

优点缺点
你可以避免创建者和具体产品之间的紧密耦合。应用工厂方法模式需要引入许多新的子类, 代码可能会因此变得更复杂。 最好的情况是将该模式引入创建者类的现有层次结构中。
能根据用户的需求定制化地创建对象。具体工厂实现逻辑不统一,增加代码理解难度。
隐藏了具体使用哪种产品来创建对象。
单一职责原则。 你可以将产品创建代码放在程序的单一位置, 从而使得代码更容易维护。
开闭原则。 无需更改现有客户端代码, 你就可以在程序中引入新的产品类型。

拓展知识

  • 在许多设计工作的初期都会使用工厂方法模式(较为简单, 而且可以更方便地通过子类进行定制),随后演化为使用抽象工厂模式、原型模式或生成器模式(更灵活但更加复杂)。
  • 抽象工厂模式通常基于一组工厂方法,但你也可以使用原型模式来生成这些类的方法。
  • 工厂方法和抽象工厂的区别:
    1. 工厂方法模式侧重于继承的连续性,核心为“里氏替换原则”;而抽象工厂模式侧重于组合的拓展性,核心为“分析共性,找出更好的抽象产品”。
    2. 工厂方法适用单产品,抽象工厂适用于多产品。


🔙 设计模式

📌最后:希望本文能够给您提供帮助,文章中有不懂或不正确的地方,请在下方评论区💬留言!

🔗参考文献:

🌐 设计模式 --refactoringguru

▶️ bilibili-趣学设计模式;黄靖锋. --拉勾教育

📖 图解设计模式 /(日)结城浩著;杨文轩译. --北京:人民邮电出版社,2017.1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
工厂方法模式是一种常见的创建型设计模式,它定义了一个用于创建对象的接口,但是由子类决定要实例化的类是哪一个。在工厂方法模式中,创建对象的过程被分离出来,使得这个过程可以被子类定制化,从而提高了代码的可扩展性和可维护性。 工厂方法模式的核心思想是将对象的创建和使用分离开来,客户端只需要知道所需对象的类型,而无需关心对象的创建过程。具体来说,工厂方法模式包含以下几个角色: 1. 抽象工厂(Abstract Factory):定义了工厂方法的接口,用于创建产品对象。 2. 具体工厂(Concrete Factory):实现抽象工厂接口,根据具体需求创建具体产品对象。 3. 抽象产品(Abstract Product):定义了产品的接口,用于描述产品的属性和行为。 4. 具体产品(Concrete Product):实现抽象产品接口,提供具体的实现。 使用工厂方法模式可以将客户端代码和具体产品的实现代码分离开来,使得代码更加灵活和可扩展。工厂方法模式在实际应用中也有很多场景,例如: 1. 当一个类不知道它所必须创建的对象的类的时候。 2. 当一个类希望由它的子类来指定所创建的对象的时候。 3. 当类将创建对象的职责委托给多个帮助子类中的某个特定子类,并且希望能够在运行时切换这些子类中的哪一个时。 总之,工厂方法模式是一种非常实用的设计模式,可以提高代码的可维护性和可扩展性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值