【发布时间】:2011-11-24 22:08:49
【问题描述】:
什么是工厂,我为什么要使用工厂?
【问题讨论】:
-
有两种不同类型的工厂模式:工厂方法模式和抽象工厂模式。你指的是哪一个?
标签: java design-patterns factory
什么是工厂,我为什么要使用工厂?
【问题讨论】:
标签: java design-patterns factory
你熟悉JDBC吗?这是一个和所有(抽象)工厂。这是一个很好的现实世界示例。
// 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。你不需要做import com.mysql.jdbc.ConnectionImpl 什么的。您只需针对java.sql.* 声明所有内容。你不需要自己做connection = new ConnectionImpl();。您只需从抽象工厂获取它作为标准 API 的一部分。
如果您将 JDBC 驱动程序类名设为可在外部配置的变量(例如属性文件)并编写与 ANSI 兼容的 SQL 查询,那么您就无需为每个单独的 Java 应用程序重写、重新编译、重建和重新分发全世界都知道的数据库供应商和/或 JDBC 驱动程序。您只需将所需的 JDBC 驱动程序 JAR 文件放在运行时类路径中并通过某些(属性)文件提供配置,而无需在您想要切换 DB 或在不同的 DB 上重用应用程序时更改任何 Java 代码行。
这就是接口和抽象工厂的力量。
另一个已知的现实世界示例是 Java EE。将“JDBC”替换为“Java EE”,将“JDBC 驱动程序”替换为“Java EE 应用服务器”(WildFly、TomEE、GlassFish、Liberty 等)。
【讨论】:
工厂设计模式非常适合需要在运行时创建对象的多个实例的情况。您可以初始化许多实例,而不是显式创建每个实例。此外,您还可以封装可以多次重复使用的复杂创建代码。
例子:
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);
}
}
}
在这个例子中,我们封装了性别初始化参数的细节,可以简单的让PersonFactory去createMale或者createFemale Person对象。
【讨论】:
简单来说,Factory 是一种 OO 设计模式,它处理创建对象而不指定要创建的对象的确切类。
使用它的一个很好的理由是明确定义in wikipedia:
创建一个对象通常需要复杂的过程,而不是 适合包含在组合对象中。对象的 创建可能会导致大量重复代码,可能需要 组成对象无法访问的信息可能无法提供 足够的抽象级别,否则可能不是 组合对象的关注点。工厂方法设计模式处理 通过定义创建对象的单独方法来解决这些问题, 然后可以覆盖哪些子类以指定的派生类型 将要创建的产品。
【讨论】:
什么是工厂?
Wikipedia详细讲解
另请参阅来自传奇的BalusC 而非here 的关于许多 GoF 模式示例的答案
简单来说,Factory 创建\初始化\分配您可以在代码中使用的对象。
例如,如果您有一个人抽象类或接口,甚至是一个具体类,并且您在其他类中声明它,例如private person; 只是该对象已声明但未创建。您将使用新的或一些依赖注入或工厂来创建此对象(还有其他选项,例如定位器等)。
我为什么要使用一个?
现在你可能需要一个特定类型的人,例如老师,甚至一个人可能会根据不同的配置进行不同的植入等。工厂模式会处理这个问题。它允许你或者我应该说让你不必担心什么实现或应使用特定类的初始化。
【讨论】:
Factory 是用于创建其他对象的对象。
它创建对象而不向客户端公开实例化逻辑。
当您不想将对象实例化逻辑暴露给客户端/调用者时,请使用此模式
相关帖子:
Design Patterns: Factory vs Factory method vs Abstract Factory
What is the basic difference between the Factory and Abstract Factory Patterns?
【讨论】:
工厂是一个对象,它创建对象。 常见的用法包括两种情况:
Integer.valueOf(),这是一种所谓的工厂方法)或根据某些条件选择具体的实现——例如提供的参数或预定义选项(参见Java API for XML Processing 中的XPathFactory 类)SomeFactory<T>)。 【讨论】: