Java 什么是静态工厂方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/929021/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:13:06  来源:igfitidea点击:

What are static factory methods?

javadesign-patternsfactory-method

提问by freddiefujiwara

What's a "static factory" method?

什么是“静态工厂”方法?

采纳答案by Matthew Flaschen

We avoid providing direct access to database connections because they're resource intensive. So we use a static factory method getDbConnectionthat creates a connection if we're below the limit. Otherwise, it tries to provide a "spare" connection, failing with an exception if there are none.

我们避免提供对数据库连接的直接访问,因为它们是资源密集型的。所以我们使用静态工厂方法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);
     //...
   }
}

回答by Bryan Kyle

A factory method a method that abstracts away the instantiation of an object. Generally factories are useful when you know that you need a new instance of a class that implements some interface but you don't know the implementing class.

工厂方法是一种抽象出对象实例化的方法。通常,当您知道需要实现某个接口的类的新实例但不知道实现类时,工厂很有用。

This is useful when working with hierarchies of related classes, a good example of this would be a GUI toolkit. You could simply hard-code calls to the constructors for concrete implementations of each widget but if you ever wanted to swap one toolkit for another you'd have a lot of places to change. By using a factory you reduce the amount of code you would need to change.

这在处理相关类的层次结构时很有用,GUI 工具包就是一个很好的例子。您可以简单地对每个小部件的具体实现的构造函数进行硬编码调用,但是如果您想将一个工具包换成另一个工具包,您将有很多地方需要更改。通过使用工厂,您可以减少需要更改的代码量。

回答by soldier.moth

  • have names, unlike constructors, which can clarify code.
  • do not need to create a new object upon each invocation - objects can be cached and reused, if necessary.
  • can return a subtype of their return type - in particular, can return an object whose implementation class is unknown to the caller. This is a very valuable and widely used feature in many frameworks which use interfaces as the return type of static factory methods.
  • 有名称,不像构造函数,可以澄清代码。
  • 不需要在每次调用时创建新对象 - 如有必要,可以缓存和重用对象。
  • 可以返回其返回类型的子类型 - 特别是,可以返回调用者未知其实现类的对象。在许多使用接口作为静态工厂方法的返回类型的框架中,这是一个非常有价值且广泛使用的特性。

fromhttp://www.javapractices.com/topic/TopicAction.do?Id=21

来自http://www.javapractices.com/topic/TopicAction.do?Id=21

回答by cwash

It all boils down to maintainability. The best way to put this is whenever you use the newkeyword to create an object, you're coupling the code that you're writing to an implementation.

这一切都归结为可维护性。最好的表达方式是,每当您使用new关键字创建对象时,您就是在将您正在编写的代码与实现耦合。

The factory pattern lets you separate how you create an object from what you do with the object. When you create all of your objects using constructors, you are essentially hard-wiring the code that uses the object to that implementation. The code that uses your object is "dependent on" that object. This may not seem like a big deal on the surface, but when the object changes (think of changing the signature of the constructor, or subclassing the object) you have to go back and rewire things everywhere.

工厂模式使您可以将创建对象的方式与对对象执行的操作分开。当您使用构造函数创建所有对象时,您实际上是将使用该对象的代码硬连接到该实现。使用您的对象的代码“依赖”于该对象。从表面上看,这似乎没什么大不了的,但是当对象发生变化时(想想更改构造函数的签名,或对对象进行子类化),您必须返回并重新连接所有地方。

Today factories have largely been brushed aside in favor of using Dependency Injection because they require a lot of boiler-plate code that turns out to be a little hard to maintain itself. Dependency Injection is basically equivalent to factories but allows you to specify how your objects get wired together declaratively (through configuration or annotations).

今天,工厂在很大程度上被搁置一边,转而支持使用依赖注入,因为它们需要大量的样板代码,而这些代码本身很难维护。依赖注入基本上等同于工厂,但允许您指定对象如何以声明方式连接在一起(通过配置或注释)。

回答by James Black

A static factory method is good when you want to ensure that only one single instance is going to return the concrete class to be used.

当您想确保只有一个实例将返回要使用的具体类时,静态工厂方法是很好的。

For example, in a database connection class, you may want to have only one class create the database connection, so that if you decide to switch from Mysql to Oracle you can just change the logic in one class, and the rest of the application will use the new connection.

例如,在一个数据库连接类中,您可能只想让一个类创建数据库连接,这样如果您决定从 Mysql 切换到 Oracle,您只需更改一个类中的逻辑,应用程序的其余部分将使用新的连接。

If you want to implement database pooling, then that would also be done without affecting the rest of the application.

如果您想实现数据库池,那么这也不会影响应用程序的其余部分。

It protects the rest of the application from changes that you may make to the factory, which is the purpose.

它保护应用程序的其余部分免受您可能对工厂所做的更改,这就是目的。

The reason for it to be static is if you want to keep track of some limited resource (number of socket connections or file handles) then this class can keep track of how many have been passed out and returned, so you don't exhaust the limited resource.

它是静态的原因是如果你想跟踪一些有限的资源(套接字连接或文件句柄的数量),那么这个类可以跟踪已经传出和返回的数量,所以你不会耗尽资源有限。

回答by Rasmus Faber

Readability can be improved by static factory methods:

静态工厂方法可以提高可读性:

Compare

相比

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.

to

public class Foo{
  public static Foo createWithBar(){
    //...
  }

  public static Foo createWithoutBar(){
    //...
  }
}

// ...

// This is much easier to read!
Foo foo = Foo.createWithBar();

回答by Jason Owen

The static factory method patternis a way to encapsulate object creation. Without a factory method, you would simply call the class's constructordirectly: Foo x = new Foo(). With this pattern, you would instead call the factory method: Foo x = Foo.create(). The constructors are marked private, so they cannot be called except from inside the class, and the factory method is marked as staticso that it can be called without first having an object.

静态工厂方法模式是一种封装对象的创建。如果没有一个工厂方法,您只需调用类的构造函数直接:Foo x = new Foo()。使用此模式,您将改为调用工厂方法: Foo x = Foo.create()。构造函数被标记为私有,因此只能从类内部调用它们,并且工厂方法被标记为static可以在没有对象的情况下调用它。

There are a few advantages to this pattern. One is that the factory can choose from many subclasses (or implementers of an interface) and return that. This way the caller can specify the behavior desired via parameters, without having to know or understand a potentially complex class hierarchy.

这种模式有几个优点。一种是工厂可以从许多子类(或接口的实现者)中进行选择并返回。通过这种方式,调用者可以通过参数指定所需的行为,而不必知道或理解潜在的复杂类层次结构。

Another advantage is, as Matthew and James have pointed out, controlling access to a limited resource such as connections. This a way to implement pools of reusable objects- instead of building, using, and tearing down an object, if the construction and destruction are expensive processes it might make more sense to build them once and recycle them. The factory method can return an existing, unused instantiated object if it has one, or construct one if the object count is below some lower threshold, or throw an exception or return nullif it's above the upper threshold.

另一个优势是,正如 Matthew 和 James 所指出的,控制对有限资源(如连接)的访问。这是一种实现可重用对象池的方法- 而不是构建、使用和拆除对象,如果构建和销毁是昂贵的过程,那么构建一次并回收它们可能更有意义。工厂方法可以返回一个现有的、未使用的实例化对象(如果它有一个),或者如果对象计数低于某个下限阈值则构造一个,或者null如果它高于上限阈值则抛出异常或返回。

As per the article on Wikipedia, multiple factory methods also allow different interpretations of similar argument types. Normally the constructor has the same name as the class, which means that you can only have one constructor with a given signature. Factories are not so constrained, which means you can have two different methods that accept the same argument types:

根据维基百科上的文章,多个工厂方法还允许对类似的参数类型进行不同的解释。通常构造函数与类同名,这意味着你只能有一个具有给定签名的构造函数。工厂不受限制,这意味着您可以使用两种不同的方法来接受相同的参数类型:

Coordinate c = Coordinate.createFromCartesian(double x, double y)

and

Coordinate c = Coordinate.createFromPolar(double distance, double angle)

This can also be used to improve readability, as Rasmus notes.

正如 Rasmus 所指出的,这也可用于提高可读性。

回答by Grygoriy Gonchar

NOTE! "The static factory methodis NOTthe same as the Factory Methodpattern" (c) Effective Java, Joshua Bloch.

笔记!“该静态工厂方法一样的工厂方法模式”(三)有效的Java,约书亚·布洛克。

Factory Method: "Define an interface for creating an object, but let the classes which implement the interface decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses" (c) GoF.

工厂方法:“定义用于创建对象的接口,但让实现该接口的类决定实例化哪个类。工厂方法让类将实例化推迟到子类”(c)GoF。

"Static factory method is simply a static method that returns an instance of a class." (c) Effective Java, Joshua Bloch. Usually this method is inside a particular class.

“静态工厂方法只是一个返回类实例的静态方法。” (c) 有效的 Java,Joshua Bloch。通常这个方法在一个特定的类中。

The difference:

区别:

The key idea of static factory method is to gain control over object creation and delegate it from constructor to static method. The decision of object to be created is like in Abstract Factory made outside the method (in common case, but not always). While the key (!) idea of Factory Method is to delegate decision of what instance of class to create inside Factory Method. E.g. classic Singleton implementation is a special case of static factory method. Example of commonly used static factory methods:

静态工厂方法的关键思想是获得对对象创建的控制并将其从构造函数委托给静态方法。要创建的对象的决定就像在抽象工厂中在方法之外做出的(在常见情况下,但并非总是如此)。而工厂方法的关键(!)思想是委托决定在工厂方法中创建哪个类的实例。例如,经典的单例实现是静态工厂方法的特例。常用静态工厂方法示例:

  • valueOf
  • getInstance
  • newInstance
  • 的价值
  • 获取实例
  • 新实例

回答by Santhosh

If the constructor of a class is private then you cannot create an object for class from outside of it.

如果一个类的构造函数是私有的,那么你不能从它的外部为类创建一个对象。

class Test{
 int x, y;
 private Test(){
  .......
  .......
  }
}

We cannot create an object for above class from outside of it. So you cannot access x, y from outside of the class. Then what is the use of this class?
Here is the Answer : FACTORYmethod.
Add the below method in above class

我们不能从它的外部为上面的类创建一个对象。所以你不能从班级外部访问 x, y 。那么这个类有什么用呢?
这是答案:FACTORY方法。
在上面的类中添加下面的方法

public static Test getObject(){
  return new Test();
}

So now you can create an object for this class from outside of it. Like the way...

所以现在你可以从它的外部为这个类创建一个对象。就像这样...

Test t = Test.getObject();

Hence, a static method which returns the object of the class by executing its private constructor is called as FACTORYmethod
.

因此,通过执行其私有构造函数返回类对象的静态方法称为FACTORY方法

回答by Thalaivar

I thought i will add some light to this post on what i know. We used this technique extensively in our recent android project. Instead of creating objects using new operatoryou can also use static methodto instantiate a class. Code listing:

我想我会根据我所知道的在这篇文章中添加一些亮点。我们在我们的recent android project. 而不是creating objects using new operator你也可以使用static method实例化一个类。代码清单:

//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();
  }
}

Static methods support conditional object creation: Each time you invoke a constructor an object will get created but you might not want that. suppose you want to check some condition only then you want to create a new object.You would not be creating a new instance of Vinoth each time, unless your condition is satisfied.

静态方法支持条件对象创建:每次调用构造函数时都会创建一个对象,但您可能不希望那样。假设您只想检查某个条件,然后才想创建一个新对象。除非满足您的条件,否则您不会每次都创建 Vinoth 的新实例。

Another example taken from Effective Java.

另一个来自Effective Java 的例子。

public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
}

This method translates a boolean primitive value into a Boolean object reference. The Boolean.valueOf(boolean)method illustrates us, it never creates an object. The ability of static factory methodsto return the same object from repeated invocationsallows classes to maintain strict control over what instances exist at any time.

此方法将布尔原始值转换为布尔对象引用。该Boolean.valueOf(boolean)方法向我们说明了,它从不创建对象。static factory methods从重复中返回相同对象的能力invocations允许类在任何时候保持对哪些实例存在的严格控制。

Static factory methodsis that, unlike constructors, they can return an objectof any subtypeof their return type. One application of this flexibility is that an API can return objects without making their classes public. Hiding implementation classes in this fashion leads to a very compact API.

Static factory methods与 不同的是constructors,它们可以返回object任何subtype它们的返回类型。这种灵活性的一个应用是 API 可以在不公开类的情况下返回对象。以这种方式隐藏实现类会导致 API 非常紧凑。

Calendar.getInstance() is a great example for the above, It creates depending on the locale a BuddhistCalendar, JapaneseImperialCalendaror by default one Georgian.

Calendar.getInstance()是一个很好的例子为上述的,它创建取决于区域设置的BuddhistCalendarJapaneseImperialCalendar或通过默认的Georgian

Another example which i could think is Singleton pattern, where you make your constructors private create an own getInstancemethod where you make sure, that there is always just one instance available.

我能想到的另一个例子是Singleton pattern,你让你的构造函数私有创建一个getInstance你自己的方法,你可以确保总是只有一个可用的实例。

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;
    }
}