静态工厂方法如何返回新实例?

时间:2013-07-28 05:22:05

标签: java factory

我一直在各地阅读,通常建议在公共构造函数上使用静态工厂方法。

其中一个优点是,与构造函数不同,静态工厂方法在每次调用时都不会创建新对象。但是,当我在this site上阅读时,该类的工厂方法

class Employee {
   private int _type;
   static final int ENGINEER = 0;
   static final int SALESMAN = 1;
   static final int MANAGER = 2;

   Employee (int type) {
       _type = type;
   }
}

定义为:

static Employee create(int type) {
     return new Employee(type);
 }

因此,为了创建一个新实例,我们

Employee eng = Employee.create(Employee.ENGINEER);

我不明白的是,是不是调用公共构造函数的工厂方法?那么它不是一遍又一次地创建一个新实例吗?

使用静态工厂方法的第二个方面我不太明白为什么没有公共/受保护构造函数的类不能被子类化?

4 个答案:

答案 0 :(得分:4)

我认为它没有正确实施。在这种情况下,构造函数不应该是private吗?拥有static工厂方法的重点是禁止直接访问使用构造函数直接从其他代码创建实例。假设您的类提供数据库连接,因为我们知道连接是资源密集型的,我们不应该不加区别地创建连接,静态工厂用于请求连接对象。工厂方法检查池中是否有空闲连接对象并返回它。 Re-usablity是一个重要的概念,它是由静态工厂方法实现的。

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

该链接中提供的代码只是它如何工作的一个示例,但不是一个很好的例子。进一步阅读:

  

使用工厂方法替换构造函数最明显的动机是使用子类替换类型代码。您有一个通常使用类型代码创建的对象,但现在需要子类。确切的子类基于类型代码。但是,构造函数只能返回所请求对象的实例。所以你需要用工厂方法替换构造函数。

回到你的问题:

  

我不明白的是,是不是调用公共构造函数的工厂方法?那么它不是一遍又一次地创建一个新实例吗?

是的,可能不应该。

  

我不太明白为什么没有公共/受保护构造函数的类不能被子类化?

即使是具有默认访问权限的构造函数,即没有访问修饰符,也可以进行子类化。但是子类应该是包的一部分。记住,一旦你创建了一个类,在创建子类的对象时,子类构造函数隐式/显式必须调用超类构造函数。现在,如果超类构造函数无法从子类构造函数中访问,因为它被标记为private,则实例化将失败。因此,子类化没有意义。

建议阅读:

  1. Consider static factory methods instead of constructors - Josh Bloch
  2. What are static factory methods in Java?

答案 1 :(得分:1)

  

其中一个优点是,与构造函数不同,静态工厂方法在每次调用时都不会创建新对象。

实际上,这更好地说明了“静态工厂方法不会必须每次调用时都创建一个新对象”。这有效地解决了您的第一个查询。 (在您的示例中,每次都创建一个新实例...但这不是使用静态工厂方法的唯一原因。)

  

使用静态工厂方法的第二个方面我不太明白为什么没有公共/受保护构造函数的类不能被子类化?

这实际上是工厂方法问题的正交。 (也不完全正确。)

您不能为没有 accessible 构造函数的类创建子类,因为JLS要求子类的每个构造函数显式或隐式调用超类构造函数。如果子类不能访问超类构造函数,则无法满足此要求。


事实上,还有另一个原因。使用static工厂方法而不是直接调用构造函数。静态工厂方法可以创建和返回不同类的实例。例如:

  // static factory method ...
  public static CharSequence createCharSequence(char[] chars, boolean mutable) {
      return mutable ? new StringBuilder(chars) : new String(chars);
  }

实际上,您可以使用非静态工厂方法和工厂对象来进一步研究。这些允许您(分别)继承和覆盖对象创建逻辑,并将对象创建逻辑与对象类本身分开。

答案 2 :(得分:0)

  

不是调用公共构造函数的工厂方法吗?那么它不是一遍又一次地创建一个新实例吗?

是的,它允许创建新对象,因此请创建私有构造函数。

在类中创建create方法。

尝试

 public class Employee {
         private int _type;
           static final int ENGINEER = 0;
           static final int SALESMAN = 1;
           static final int MANAGER = 2;
         public static   Employee INSTANCE;
         public static final Employee create(int type)
         {
           if(INSTANCE==null)
           {
               INSTANCE=new Employee(type);
           }
           return INSTANCE;
         }
           private Employee (int type) {
               _type = type;
           }
    }

新对象也是通过clone创建的。您可以覆盖Object类的clone()方法以抛出 CloneNotSupportedException 异常。

答案 3 :(得分:0)

  

我一直在各地读书,通常建议使用   公共构造函数的静态工厂方法。

实际上,我不认为这样做是正确或可取的。工厂模式有自己的用途,不能取代公共构造函数提供的功能。 “公共建设者”被提供来决定其他班级将如何创建你的班级。添加一个简单的包装器静态函数是没有意义的,除了接受与构造函数相同的参数并创建代码中所示的对象之外,它不会做任何其他事情。这样做是工厂模式的误区。

“工厂模式”是仅在需要基于输入参数的不同类的INSTANTIATION LOGIC时才需要的创建模式。在您的例如,如果Engineer,Salesman和Manager是从同一Employee类派生的不同类,并且基于类型构造适当的类,则需要工厂。

设计可以在预期所需功能的情况下完成,但我认为,只需设计手头的功能并在需要时进行修改就好了。