什么是静态工厂方法?

发布于 2024-07-22 06:40:40 字数 19 浏览 6 评论 0原文

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

What's a "static factory" method?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

橘寄 2024-07-29 06:40:40

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

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

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

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

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

正如 Rasmus 指出的那样,这

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

也可以用于提高可读性。

The static factory method pattern is a way to encapsulate object creation. Without a factory method, you would simply call the class's constructor directly: 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 static so that it can be called without first having an object.

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 null if it's above the upper threshold.

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.

尘世孤行 2024-07-29 06:40:40

笔记! “静态工厂方法工厂方法模式相同”(c)Effective Java,Joshua Bloch。

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

“静态工厂方法只是返回类实例的静态方法。” (c) 有效的 Java,Joshua Bloch。 通常此方法位于特定类内。

区别:

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

  • valueOf
  • getInstance
  • newInstance

NOTE! "The static factory method is NOT the same as the Factory Method pattern" (c) Effective Java, Joshua Bloch.

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.

"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.

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
终弃我 2024-07-29 06:40:40

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

We avoid providing direct access to database connections because they're resource intensive. So we use a static factory method getDbConnection that 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.

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);
     //...
   }
}
悲歌长辞 2024-07-29 06:40:40

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

比较

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.

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

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

// ...

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

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();
末骤雨初歇 2024-07-29 06:40:40
  • 与构造函数不同,有名称,可以澄清代码。
  • 不需要在每次调用时创建一个新对象 - 对象
    如有必要,可以缓存和重用。
  • 可以返回其返回类型的子类型 - 特别是,可以
    返回一个对象,其实现类对于调用者来说是未知的。
    这是一个非常有价值且在许多框架中广泛使用的功能
    它使用接口作为静态工厂方法的返回类型。

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

  • 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

我们的影子 2024-07-29 06:40:40

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

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

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

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

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).

东京女 2024-07-29 06:40:40

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

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

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

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

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

Test t = Test.getObject();

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

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 : FACTORY method.
Add the below method in above class

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 FACTORY method
.

热情消退 2024-07-29 06:40:40

我想我会在这篇文章中添加一些我所知道的内容。 我们在最近的 android 项目中广泛使用了这种技术。 除了使用 new 运算符创建对象之外,您还可以使用静态方法来实例化类。 代码清单:

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

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

另一个例子取自Effective Java

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

此方法将布尔原始值转换为布尔对象引用。 Boolean.valueOf(boolean) 方法向我们说明,它从不创建对象。 静态工厂方法能够从重复的调用中返回相同的对象,这使得类能够对任何时候存在的实例保持严格的控制。

静态工厂方法的特点是,与构造函数不同,它们可以返回其返回类型的任何子类型对象。 这种灵活性的一个应用是 API 可以返回对象而无需公开其类。 以这种方式隐藏实现类会产生非常紧凑的 API。

Calendar.getInstance() 是上述内容的一个很好的例子,它根据语言环境创建一个 BuddhistCalendarJapanImperialCalendar 或默认创建一个 Georgian

我想到的另一个例子是单例模式,您可以将构造函数设为私有,创建一个自己的 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;
    }
}

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 operator you can also use static method to instantiate a class. Code listing:

//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.

Another example taken from 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 methods to return the same object from repeated invocations allows classes to maintain strict control over what instances exist at any time.

Static factory methods is that, unlike constructors, they can return an object of any subtype of 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.

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

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

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;
    }
}
薄荷→糖丶微凉 2024-07-29 06:40:40

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

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

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.

不打扰别人 2024-07-29 06:40:40

静态工厂的优点之一是该 API 可以返回对象而无需公开其类。 这导致 API 非常紧凑。 在 java 中,这是通过 Collections 类实现的,该类隐藏了大约 32 个类,这使得集合 API 非常紧凑。

One of the advantages that stems from Static factory is that that API can return objects without making their classes public. This lead to very compact API. In java this is achieved by Collections class which hides around 32 classes which makes it collection API very compact.

骷髅 2024-07-29 06:40:40

具有私有构造函数的静态工厂方法的优点之一(必须限制外部类的对象创建,以确保不会在外部创建实例)是您可以创建实例控制的类。 实例控制类保证在程序运行期间不存在两个相等的不同实例(a.equals(b) 当且仅当 a==b),这意味着您可以使用以下命令检查对象的相等性根据Effective java.io,== 运算符而不是 equals 方法。

静态工厂方法返回相同对象的能力
重复调用允许类保持严格的控制
任何时候都存在哪些实例。 据说执行此操作的类是
实例控制。 写的原因有几个
实例控制的类。 实例控制允许类
保证它是单例(第 3 项)或不可实例化(第 4 项)。
此外,它允许一个不可变的类(第 15 条)来做出保证
不存在两个相等的实例:a.equals(b) 当且仅当 a==b。 如果
一个类做出了这样的保证,那么它的客户端就可以使用 == 运算符
而不是 equals(Object) 方法,这可能会导致改进
表现。 枚举类型(第 30 项)提供了这种保证。

摘自《Effective Java》,Joshua Bloch(第 1 条,第 6 页)

One of the advantages of the static factory methods with private constructor(object creation must have been restricted for external classes to ensure instances are not created externally) is that you can create instance-controlled classes. And instance-controlled classes guarantee that no two equal distinct instances exist(a.equals(b) if and only if a==b) during your program is running that means you can check equality of objects with == operator instead of equals method, according to Effective java.

The ability of static factory methods to return the same object from
repeated invocations allows classes to maintain strict control over
what instances exist at any time. Classes that do this are said to be
instance-controlled. There are several reasons to write
instance-controlled classes. Instance control allows a class to
guarantee that it is a singleton (Item 3) or noninstantiable (Item 4).
Also, it allows an immutable class (Item 15) to make the guarantee
that no two equal instances exist: a.equals(b) if and only if a==b. If
a class makes this guarantee, then its clients can use the == operator
instead of the equals(Object) method, which may result in improved
performance. Enum types (Item 30) provide this guarantee.

From Effective Java, Joshua Bloch(Item 1,page 6)

凤舞天涯 2024-07-29 06:40:40

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

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

如果您想实现数据库池,那么也可以在不影响应用程序其余部分的情况下完成。

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

它是静态的原因是,如果您想跟踪某些有限的资源(套接字连接或文件句柄的数量),那么此类可以跟踪已传递和返回的资源数量,这样您就不会耗尽资源资源有限。

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.

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.

吻风 2024-07-29 06:40:40

静态

使用关键字“static”声明的成员。

工厂方法

创建和返回新对象的方法。

在Java中

编程语言中与“静态”的含义相关,但与“工厂”的定义无关。

static

A member declared with the keyword 'static'.

factory methods

Methods that create and return new objects.

in Java

The programming language is relevant to the meaning of 'static' but not to the definition of 'factory'.

韵柒 2024-07-29 06:40:40

Java实现包含实用程序类java.util.Arraysjava.util.Collections,它们都包含静态工厂方法,它的示例以及如何使用:

另外java.lang.String类也有这样的静态工厂方法

  • String.format(...)、String.valueOf(..)、String.copyValueOf(...)

Java implementation contains utilities classes java.util.Arrays and java.util.Collections both of them contains static factory methods, examples of it and how to use :

Also java.lang.String class have such static factory methods:

  • String.format(...), String.valueOf(..), String.copyValueOf(...)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文