Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用工厂方法进行对象实例化_Java_Oop - Fatal编程技术网

Java 使用工厂方法进行对象实例化

Java 使用工厂方法进行对象实例化,java,oop,Java,Oop,我目前参加了CS2课程(数据结构),其中Java是使用的语言,我对使用传统构造函数方法与工厂方法比较和对比对象实例化感兴趣。一个代表了比另一个更高的计算优雅度吗?工厂方法是否会以类似于参数化构造函数的方式处理参数?例如: public class Tester { private String name; private int age; // Parameterized constructor public Tester(String myName, in

我目前参加了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; 
    }
} 
本质上,我很好奇如何编写一个等效的工厂方法,以及这样做的潜在好处是什么

谢谢


~Caitlin

工厂方法很好,因为它们可以返回对对象的引用,而对象不一定是该类的实例。它可以返回那个类、一个子类型,甚至
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
    }
} 

工厂在特定情况下非常有用:

  • 其中,可能会根据参数返回对象的几个不同子类之一
  • 有些地方需要“保护”对象的创建,可能是为了安全,可能是为了某种同步
  • 其中创建的对象需要在创建后以某种方式“注册”,而在构造函数中这样做是不可行的
  • 除非必须创建实例,否则人们甚至不想加载(实际的)类(以及它的引用类树)
  • 如果没有上述原因,工厂方法就没有好处,它们只是模糊了逻辑

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

    添加:以解决“继承”问题--

    假设我们有一个经典的车辆示例,其中包含Car和Truck子类。如果您只是拥有CarFactory和TruckFactory,那么这就增加了代码的复杂性,没有什么好的理由(除非有其他令人信服的理由使用工厂)

    但你可以有一个汽车工厂,让它根据输入或外部因素“决定”生产汽车或卡车。这是一种相当常见的模式


    但是,如果您(出于某种原因)拥有一个只创建车辆对象(而不是汽车或卡车)的VehicleFactory,并且如果强制使用该工厂(您无法访问车辆的构造器),则基本上不可能对车辆进行子类化。当您使用工厂时,您会使其他人很难(至少)添加新的子类。

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

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

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

    • 与构造函数不同,静态工厂方法可以返回任何对象,只要返回的对象匹配或是返回类型的子类。这将启用基于接口的类型系统。Java1.5的Enum框架利用了这一点:EnumSet类没有公共构造函数,只有静态工厂。静态工厂返回的实际对象因枚举的大小而异


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

    看看这个:Joshua Bloch的Essential Java,第2版中的第1项是关于赞美静态工厂方法的优点和许多优点,作为构造函数获取对新实例化对象的引用的真正替代方法。EssentialJava对于任何希望获得Java专业知识的人来说都是一本极好的读物(出于许多原因)。我建议您获取并阅读它。工厂方法模式的一个真实示例是
    ExecutorService es=Executors。newXxxThreadPool()
    对于设计用于继承的类,静态工厂方法通常不是好的选择。@scottb您能解释一下为什么吗?我打算读“基本Java”,但同时…非常好。非常感谢。