Java 什么是静态工厂方法?
什么是“静态工厂”方法?工厂方法抽象对象实例化的方法。通常,当您知道需要实现某个接口的类的新实例,但不知道实现的类时,工厂非常有用 这在处理相关类的层次结构时非常有用,GUI工具包就是一个很好的例子。您可以简单地为每个小部件的具体实现对构造函数进行硬编码调用,但是如果您想要将一个工具箱替换为另一个工具箱,您将有很多地方需要更改。通过使用工厂,您可以减少需要更改的代码量Java 什么是静态工厂方法?,java,design-patterns,factory-method,Java,Design Patterns,Factory Method,什么是“静态工厂”方法?工厂方法抽象对象实例化的方法。通常,当您知道需要实现某个接口的类的新实例,但不知道实现的类时,工厂非常有用 这在处理相关类的层次结构时非常有用,GUI工具包就是一个很好的例子。您可以简单地为每个小部件的具体实现对构造函数进行硬编码调用,但是如果您想要将一个工具箱替换为另一个工具箱,您将有很多地方需要更改。通过使用工厂,您可以减少需要更改的代码量 与构造函数不同,构造函数可以澄清代码 不需要在每次调用时创建新对象-对象 如有必要,可以缓存和重用 可以返回其返回类型的子类型
- 与构造函数不同,构造函数可以澄清代码
- 不需要在每次调用时创建新对象-对象 如有必要,可以缓存和重用
- 可以返回其返回类型的子类型-尤其是可以 返回调用方未知其实现类的对象。 这是许多框架中非常有价值和广泛使用的特性 它使用接口作为静态工厂方法的返回类型
从我们避免提供对数据库连接的直接访问,因为它们是资源密集型的。因此,我们使用一个静态工厂方法
getDbConnection
,如果低于限制,它将创建一个连接。否则,它会尝试提供一个“备用”连接,如果没有,则会出现异常
public class DbConnection{
private static final int MAX_CONNS = 100;
private static int totalConnections = 0;
private static Set<DbConnection> availableConnections = new HashSet<DbConnection>();
private DbConnection(){
// ...
totalConnections++;
}
public static DbConnection getDbConnection(){
if(totalConnections < MAX_CONNS){
return new DbConnection();
}else if(availableConnections.size() > 0){
DbConnection dbc = availableConnections.iterator().next();
availableConnections.remove(dbc);
return dbc;
}else {
throw new NoDbConnections();
}
}
public static void returnDbConnection(DbConnection dbc){
availableConnections.add(dbc);
//...
}
}
公共类数据库连接{
专用静态最终int MAX_CONNS=100;
私有静态int totalConnections=0;
私有静态集availableConnections=new HashSet();
专用数据库连接(){
// ...
totalConnections++;
}
公共静态DbConnection getDbConnection(){
if(总连接数<最大连接数){
返回新的DbConnection();
}else if(availableConnections.size()>0){
DbConnection dbc=availableConnections.iterator().next();
可用连接。删除(dbc);
返回dbc;
}否则{
抛出新节点连接();
}
}
公共静态void returnDbConnection(DbConnection dbc){
availableConnections.add(dbc);
//...
}
}
这一切归结为可维护性。最好的方法是,无论何时使用new
关键字创建对象,都要将正在编写的代码耦合到一个实现
factory模式允许您将创建对象的方式与处理对象的方式分开。当您使用构造函数创建所有对象时,实际上是在将使用该对象的代码硬连接到该实现。使用对象的代码“依赖于”该对象。从表面上看,这似乎不是什么大事,但当对象发生变化时(考虑更改构造函数的签名或对象的子类化),您必须返回并重新布线
今天,工厂在很大程度上被搁置在使用依赖注入的一边,因为它们需要大量的锅炉板代码,而这些代码本身有点难以维护。依赖项注入基本上等同于工厂,但允许您指定对象如何以声明方式连接在一起(通过配置或注释)。当您希望确保只有一个实例返回要使用的具体类时,静态工厂方法很好 例如,在一个数据库连接类中,您可能只希望有一个类创建数据库连接,因此,如果您决定从Mysql切换到Oracle,您只需更改一个类中的逻辑,应用程序的其余部分将使用新连接 如果希望实现数据库池,那么也可以在不影响应用程序其余部分的情况下实现 它保护应用程序的其余部分不受您可能对工厂所做的更改的影响,这正是它的目的
它是静态的原因是,如果您想跟踪某些有限的资源(套接字连接数或文件句柄数),则此类可以跟踪传递和返回的数量,这样您就不会耗尽有限的资源。静态工厂方法可以提高可读性: 比较
public class Foo{
public Foo(boolean withBar){
//...
}
}
//...
// What exactly does this mean?
Foo foo = new Foo(true);
// You have to lookup the documentation to be sure.
// Even if you remember that the boolean has something to do with a Bar
// you might not remember whether it specified withBar or withoutBar.
到
是封装对象创建的一种方法。如果没有工厂方法,您只需直接调用类的:foox=newfoo()
。使用此模式,您可以调用工厂方法:foox=Foo.create()
。构造函数被标记为private,因此只能从类内部调用它们,而工厂方法被标记为private,这样就可以在没有对象的情况下调用它
这种模式有一些优点。一个是工厂可以从许多子类(或接口的实现者)中选择并返回该子类。这样,调用方可以通过参数指定所需的行为,而不必知道或理解潜在的复杂类层次结构
另一个优势是,正如Matthew和James所指出的,控制对有限资源(如连接)的访问。这是一种实现方法——如果构建和销毁过程成本高昂,那么一次构建并回收它们可能更有意义,而不是构建、使用和拆卸对象。factory方法可以返回现有的、未使用的实例化对象(如果有),或者在对象计数低于某个较低阈值时构造一个,或者在高于较高阈值时抛出异常或返回null
根据维基百科上的文章,多工厂方法也允许对类似的参数类型进行不同的解释。通常,构造函数与类具有相同的名称,这意味着您只能有一个具有给定名称的构造函数。工厂没有那么多限制,这意味着你可以有两个dif
public class Foo{
public static Foo createWithBar(){
//...
}
public static Foo createWithoutBar(){
//...
}
}
// ...
// This is much easier to read!
Foo foo = Foo.createWithBar();
Coordinate c = Coordinate.createFromCartesian(double x, double y)
Coordinate c = Coordinate.createFromPolar(double distance, double angle)
class Test{
int x, y;
private Test(){
.......
.......
}
}
public static Test getObject(){
return new Test();
}
Test t = Test.getObject();
//instantiating a class using constructor
Vinoth vin = new Vinoth();
//instantiating the class using static method
Class Vinoth{
private Vinoth(){
}
// factory method to instantiate the class
public static Vinoth getInstance(){
if(someCondition)
return new Vinoth();
}
}
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
public class Singleton{
//initailzed during class loading
private static final Singleton INSTANCE = new Singleton();
//to prevent creating another instance of Singleton
private Singleton(){}
public static Singleton getSingleton(){
return INSTANCE;
}
}