3

我目前正在参加一个 CS2 课程(数据结构),其中使用了 Java 语言,并且我有兴趣比较和对比使用传统构造函数方法和工厂方法的对象实例化。一个比另一个代表更高程度的计算优雅吗?工厂方法会以类似于参数化构造函数的方式处理参数吗?例如:

public class Tester
{
    private String name;
    private int age;

    // Parameterized constructor  
    public Tester(String myName, int myAge)
    {
        this.name = myName;
        this.age = myAge; 
    }
} 

本质上,我很好奇如何编写等效的工厂方法以及这样做的潜在好处。

谢谢,

~凯特琳

4

3 回答 3

3

工厂方法很好,因为它们可以返回对不一定是该类实例的对象的引用。它可以返回该类、子类型,甚至null,并且通常以他们希望方法可以的任何方式进行。因此,您可以将选择类型的逻辑移动到您自己的代码中。您可以在适当的情况下返回现有实例,从而节省堆空间等。

另一个基本的伪示例是Integer.forValue()可以实习一个整数,因此不会无缘无故地重新创建相同的不可变对象。另请参阅Executors.newXxxThreadPool()

一个基本的例子:

public class Tester
{
    private String name;
    private int age;

    // Parameterized constructor  
    private Tester(String myName, int myAge)
    {
        this.name = myName;
        this.age = myAge; 
    }
    public static Tester getTester(String mn, int ag){
        if(age>0){return new Tester(mn, ag);}
        else if(age>80){return new OldPersonThatExtendsTester(mn, ag);} 
        //we'd need a public or otherwise accessible constructor above. It's a subtype!
        else {return null;} //yes, this is possible
    }
} 
于 2013-09-13T22:47:31.310 回答
2

工厂在特定情况下很有用:

  1. 根据参数,可能会返回对象的几个不同子类之一。
  2. 在需要“保护”对象的创建的地方,也许是为了安全,也许是为了某种同步。
  3. 创建的对象需要在创建后以某种方式“注册”,并且在构造函数中这样做是不可行的。
  4. 除非必须创建实例,否则甚至不想加载(实际)类(并且它是引用类的树)。

在不存在上述某些原因的情况下,工厂方法没有任何好处,它们只会模糊逻辑。

工厂可以做什么并没有真正的限制,因为它可以(如果设置正确)访问 hoi polloi 无法访问的包级构造函数和接口。

补充: 为了解决“继承”问题——

假设我们有经典的 Vehicle 示例,其中包含 Car 和 Truck 子类。如果您只是拥有 CarFactory 和 TruckFactory,那么这会无缘无故地增加代码的复杂性(除非有其他令人信服的理由使用工厂)。

但是您可以拥有一个 VehicleFactory 并让它根据输入或外部因素“决定”创建汽车或卡车。这是一个相当普遍的模式。

但是,如果您(出于某种原因)拥有一个仅创建 Vehicle 对象(而不是 Cars 或 Trucks)的 VehicleFactory,并且如果必须使用该工厂(您无法访问 Vehicle 的构造函数),那么这基本上是不可能的子类车辆。当您使用工厂时,(至少)其他人很难添加新的子类。

于 2013-09-13T22:52:51.937 回答
2

根据 Effective Java 中合理的观察,静态工厂方法的主要优点如下:

  • 您可以为它们命名,与必须始终以类命名的构造函数不同。这使代码更具可读性,并且可以避免由于参数类型相同等原因可能无法重载构造函数的丑陋情况。在这种情况下,您可以轻松地提供两个具有不同名称的工厂方法来指示差异。

  • 与必须创建新实例的构造函数不同,静态工厂方法不需要实际实例化任何东西。因此,静态工厂方法对于实例控制的类(例如单例类)是必不可少的。

  • 与构造函数不同,静态工厂方法可以返回任何对象,只要返回的对象匹配或者是返回类型的子类。这使基于接口的类型系统成为可能。Java 1.5 的 Enum 框架利用了这一点:EnumSet 类没有公共构造函数,只有静态工厂。静态工厂返回的实际对象取决于枚举的大小。

静态工厂的主要缺点是它们不能成为为继承而设计的类的基础。不能对仅提供私有构造函数的类进行子类化。静态工厂方法的一个小缺点是它们无法与其他静态方法区分开来,因此为了使读者能够识别它们,它们通常遵循命名模式(如果将这样的命名模式设计为​​标记注释,则可以对其进行注释对于静态工厂方法)。

于 2013-09-14T04:17:21.877 回答