2

我一直在不同的地方读到,通常建议使用静态工厂方法而不是公共构造函数。

优点之一是与构造函数不同,静态工厂方法不会在每次调用时创建新对象。但是,正如我在此站点上所读到的,该类的工厂方法

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

4 回答 4

4

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

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

该链接中提供的代码只是其工作原理的一个示例,但并不是一个很好的示例。进一步阅读:

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

回到你的问题:

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

是的,可能不应该。

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

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

推荐阅读:

  1. 考虑静态工厂方法而不是构造函数 - Josh Bloch
  2. Java中的静态工厂方法是什么?
于 2013-07-28T05:28:20.553 回答
1

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

实际上,最好将其表述为“静态工厂方法不一定在每次调用时都创建一个新对象”。这有效地解决了您的第一个查询。(在您的示例中,它确实每次都会创建一个新实例......但这不是使用静态工厂方法的唯一原因。)

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

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

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


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

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

事实上,您可以通过非静态工厂方法和工厂对象进一步实现这一点。这些允许您(分别)继承和覆盖对象创建逻辑,并将对象创建逻辑与对象类本身分开。

于 2013-07-28T05:48:20.070 回答
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异常。

于 2013-07-28T05:29:19.723 回答
0

我一直在不同的地方读到,通常建议使用静态工厂方法而不是公共构造函数。

实际上,我不认为这样做是正确的或可取的。工厂模式有它自己的用途,不能替代公共构造函数提供的功能。提供“公共构造函数”来指示其他类将如何创建您的类。添加一个简单的包装静态函数是没有意义的,它除了接受与构造函数相同的参数并创建代码中所示的对象外,什么都不做。这样做是对工厂模式的误用。

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

可以在预期所需功能的情况下进行设计,但是,我认为,为手头的功能进行设计并在需要时对其进行修改要好得多。

于 2013-07-28T07:18:50.583 回答