Oop 构造函数与工厂方法

Oop 构造函数与工厂方法,oop,ooad,Oop,Ooad,建模类时,首选的初始化方式是什么: 构造器,或 工厂方法 使用这两种方法的考虑因素是什么 在某些情况下,我更喜欢使用工厂方法,如果无法构造对象,该方法将返回null。这使得代码整洁。与从构造函数中抛出异常相比,我可以在采取其他操作之前简单地检查返回值是否不为null。(我个人不喜欢例外情况) 比如说,我在一个类上有一个构造函数,它需要一个id值。构造函数使用此值从数据库填充类。如果指定id的记录不存在,构造函数将抛出RecordNotFoundException。在这种情况下,我必须将所有此类类

建模类时,首选的初始化方式是什么:

  • 构造器,或
  • 工厂方法
  • 使用这两种方法的考虑因素是什么

    在某些情况下,我更喜欢使用工厂方法,如果无法构造对象,该方法将返回null。这使得代码整洁。与从构造函数中抛出异常相比,我可以在采取其他操作之前简单地检查返回值是否不为null。(我个人不喜欢例外情况)

    比如说,我在一个类上有一个构造函数,它需要一个id值。构造函数使用此值从数据库填充类。如果指定id的记录不存在,构造函数将抛出RecordNotFoundException。在这种情况下,我必须将所有此类类的构造包含在try..catch块中

    与此相反,我可以在这些类上使用一个静态工厂方法,如果找不到记录,该方法将返回null


    在这种情况下,哪种方法更好,构造函数还是工厂方法?

    默认情况下,构造函数应该是首选方法,因为它们更易于理解和编写。但是,如果您特别需要将对象的构造细节与客户机代码所理解的语义分离,那么最好使用工厂

    构造函数和工厂之间的区别类似于变量和指向变量的指针。还有另一个间接层次,这是一个缺点;但也有另一种灵活性,这是一种优势。因此,在做出选择时,建议您进行成本效益分析。

    摘自第108页,共页

    在以下情况下使用Factory方法模式:

    • 类不能预测它必须创建的对象类
    • 类希望其子类指定它创建的对象
    • 类将职责委托给几个助手子类中的一个,并且您希望本地化哪个助手子类是委托的知识

    问问自己它们是什么,为什么我们有它们。它们都用于创建对象的实例

    ElementarySchool school = new ElementarySchool();
    ElementarySchool school = SchoolFactory.Construct(); // new ElementarySchool() inside
    
    到目前为止没有差别。现在想象一下,我们有各种类型的学校,我们想从使用初等学校切换到高中(这是从初等学校衍生出来的,或者实现了与初等学校相同的接口ISchool)。代码更改将是:

    HighSchool school = new HighSchool();
    HighSchool school = SchoolFactory.Construct(); // new HighSchool() inside
    
    如果是接口,我们将有:

    ISchool school = new HighSchool();
    ISchool school = SchoolFactory.Construct(); // new HighSchool() inside
    
    现在,如果您在多个地方有这段代码,您可以看到使用工厂方法可能非常便宜,因为一旦您更改了工厂方法,您就完成了(如果我们使用第二个带有接口的示例)

    这是主要的区别和优势。当您开始处理一个复杂的类层次结构,并且希望从这样的层次结构中动态创建一个类的实例时,您会得到以下代码。然后,工厂方法可能会接受一个参数,该参数告诉方法要实例化哪个具体实例。假设您有一个MyStudent类,您需要实例化相应的ISchool对象,以便您的学生是该学校的成员

    ISchool school = SchoolFactory.ConstructForStudent(myStudent);
    
    现在,您的应用程序中有一个位置包含业务逻辑,用于确定要为不同的IStudent对象实例化的ISchool对象

    所以-对于简单类(值对象等),构造函数很好(您不想过度设计应用程序),但对于复杂类层次结构,工厂方法是首选方法


    这样,您就遵循了从“程序到接口,而不是实现”的第一条设计原则。

    仅当您需要对对象创建进行额外控制时,才使用工厂,这是构造函数无法做到的

    例如,工厂可以进行缓存

    另一种使用工厂的方法是在您不知道要构造的类型的场景中。在插件工厂场景中经常会看到这种用法,每个插件都必须派生自基类或实现某种接口。工厂创建从BaseCLASS派生的类或实现接口的实例。

    < p>您需要读取(如果您有权访问)<强>项目1:考虑静态工厂方法,而不考虑构造函数< /强> ./p> 静态工厂方法的优点:

  • 他们有名字
  • 它们不需要在每次被调用时创建新对象
  • 它们可以返回其返回类型的任何子类型的对象
  • 它们减少了创建参数化类型实例的繁琐性
  • 静态工厂方法的缺点:

  • 当只提供静态工厂方法时,没有公共或受保护构造函数的类不能被子类化
  • 它们不容易与其他静态方法区分开来

  • 来自CAD/CAM应用程序的具体示例

    切割路径将通过使用构造函数生成。它是定义要切割的路径的一系列直线和圆弧。虽然直线和圆弧的序列可能不同,并且具有不同的坐标,但通过将列表传递到构造函数中,可以轻松地对其进行处理

    将使用工厂制作形状。因为虽然有一个shape类,但每个形状的设置都会根据它是什么类型的形状而有所不同。我们不知道在用户做出选择之前,我们将初始化什么形状。

    < P>引用“有效java”,第二版,项目1:考虑静态工厂方法而不是构造函数P。5:

    请注意,静态工厂方法与工厂方法模式不同 来自设计模式[Gamma95,第107页]。中描述的静态工厂方法 此项在设计模式中没有直接等效项。”

    比如说,我在一个类上有一个构造函数,它需要一个id值。构造函数使用此值从数据库填充类

    这个
    var value = new Instance(1, 2).init()
    public function init() {
        try {
            doSome()
        }
        catch (e) {
            soAnotherSome()
        }
    }
    
    Complex complex = new Complex(23.0);
    
    Complex complex = Complex.fromRealNumber(23.0);