关于java:简单来说,什么是工厂?

In simplest terms, what is a factory?

什么是工厂?我为什么要用?


你熟悉JDBC吗?它是一个抽象的工厂。这是一个很好的现实例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Factory method. Loads the driver by given classname. It actually returns a
// concrete Class<Driver>. However, we don't need it here, so we just ignore it.
// It can be any driver class name. The MySQL one here is just an example.
// Under the covers, it will do DriverManager.registerDriver(new Driver()).
Class.forName("com.mysql.jdbc.Driver");

// Abstract factory. This lets the driver return a concrete connection for the
// given URL. You can just declare it against java.sql.Connection interface.
// Under the covers, the DriverManager will find the MySQL driver by URL and call
// driver.connect() which in turn will return new ConnectionImpl().
Connection connection = DriverManager.getConnection(url);

// Abstract factory. This lets the driver return a concrete statement from the
// connection. You can just declare it against java.sql.Statement interface.
// Under the covers, the MySQL ConnectionImpl will return new StatementImpl().
Statement statement = connection.createStatement();

// Abstract factory. This lets the driver return a concrete result set from the
// statement. You can just declare it against java.sql.ResultSet interface.
// Under the covers, the MySQL StatementImpl will return new ResultSetImpl().
ResultSet resultSet = statement.executeQuery(sql);

您的代码中不需要有一行特定于JDBC驱动程序的import。你不需要做任何事情。你只需申报所有针对java.sql.*的东西。你不需要自己动手。您只需要从一个抽象工厂获得它作为标准API的一部分。

如果将JDBC驱动程序类名称命名为可以在外部配置的变量(例如,属性文件),并编写ANSI兼容SQL查询,那么您就不必为世界所知的每一个数据库供应商和/或JDBC驱动程序重写、重新编译、重建和重新分配Java应用程序。您只需在运行时类路径中删除所需的JDBC驱动程序JAR文件,并提供一些(属性)文件的配置,而不需要更改任何Java代码行,只要您想切换DB或在不同的DB上重用应用程序。

这就是接口和抽象工厂的力量。

另一个已知的真实世界例子是JavaEE。将"JDBC"与"JavaEE"和"JDBC驱动程序"替换为"JavaEE应用服务器"(FielF飞、TomEE、GelasFISH、Reland等)。

参见:

  • Class#forName()DriverManager#getConnection()的工作原理是什么?
  • JavaEE究竟是什么?
  • 维基百科:工厂方法模式
  • 维基百科:抽象工厂模式

简单地说,工厂是一个面向对象的设计模式,它处理创建对象,而不指定要创建的对象的确切类。

在维基百科中有一个很好的理由来使用它:

The creation of an object often requires complex processes not
appropriate to include within a composing object. The object's
creation may lead to a significant duplication of code, may require
information not accessible to the composing object, may not provide a
sufficient level of abstraction, or may otherwise not be part of the
composing object's concerns. The factory method design pattern handles
these problems by defining a separate method for creating the objects,
which subclasses can then override to specify the derived type of
product that will be created.


当您需要在运行时创建一个对象的多个实例时,工厂设计模式是理想的。您可以初始化许多实例,而不是显式地创建每个实例。此外,还可以封装可多次重复使用的复杂创建代码。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Person {
    int ID;
    String gender;
    public Person(int ID,String gender){
        this.ID=ID;
        this.gender=gender;
    }
    public int getID() {
        return ID;
    }
    public String getGender() {
        return gender;
    }
}
public class PersonFactory{
    public static Person createMale(int id){
        return new Person(id,"M");
    }
    public static Person createFemale(int id){
        return new Person(id,"F");
    }
}
public class factorytest{
    public static void main(String[]args){
        Person[] pList= new Person[100];
        for(int x=0;x<100;x++){
            pList[x]=PersonFactory.createMale(x);
        }
    }
}

在这个例子中,我们封装了gender初始化参数的详细信息,并且可以简单地要求personFactory创建male或createwome person对象。


What is a factory ?

维基百科详细解释

也可以在这里看到传奇的Balusc关于许多gof模式示例的答案。简单来说,工厂创建初始化分配可以在代码中使用的对象。例如,如果您有一个Person抽象类或接口,甚至是一个具体的类,并且您在另一个类(如private person;中)中声明了它,那就是该对象已经声明,但尚未创建。您将使用新的或某些依赖项注入或工厂来创建此对象(还有其他选项,例如定位器等)。

Why would I want to use one?

现在你可能需要一个特定类型的人,例如老师,甚至是人,可能有不同的植入,基于不同的配置等。工厂模式负责这一点。它允许你或者我应该说,让你不用担心应该使用什么实现或初始化特定的类。


工厂是用于创建其他对象的对象。

它创建对象,而不向客户机公开实例化逻辑。

当您不想向客户机/调用者公开对象实例化逻辑时,使用此模式

相关员额:

设计模式:工厂vs工厂方法vs抽象工厂

工厂模式和抽象工厂模式的基本区别是什么?


工厂是一个创建对象的对象。常见用法包括两种情况:

  • 当您希望将具体对象的选择委托给工厂时,例如,它可以返回已经存在的对象(参见EDCOX1×0),这是所谓的工厂方法,或者根据一些条件选择具体的实现方式——例如提供的参数或预定义的选项(参见Java API中的EDCOX1 OR 1类XML处理)
  • 当你想要更灵活的工作时。不能将方法或构造函数作为参数传递(当然可以,但反射很糟糕),因此可以使用具体工厂作为对象源(例如,泛型方法中的SomeFactory)。