`
TonyLian
  • 浏览: 401506 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【第1条】考虑用静态工厂方法代替构造函数

阅读更多

《第2章》创建和销毁对象(第1~6条)

 

 【第1条】考虑用静态工厂方法代替构造函数

 

所谓静态工厂方法,实际上只是一个简单的静态方法,它返回的是类的一个实例。

使用静态工厂方法的好处:

1)它与构造函数不同,它有名字,你可以把名字起的更易于阅读。

      如果你想让2个构造函数拥有相同个数和类型的参数,这将是无法实现的;即使是2个不同类型的参数顺序倒置的,使用者也非常容易搞混乱。

一个例子来自【第13条】,一个类Complex(复数,就是数学课上学的,有实数部和虚数部的那个东东)

对它的构造可能有这样2种需求:

 a)分别给出实数部和虚数部来构造之;

 b)基于极坐标来构造(提供“半径”和“角度”)

那么很显然这2中构造方式,都是由2个float型参数的,对于构造函数将无能为力,而静态工厂方法可以从方法名来区别开,而且还带来了易于辨识的好处:

public class Complex {
    
    private final float re;
    private final float im;

    private Complex(float re, float im){
        this.re = re;
        this.im = im;
    }

    public static Complex valueOf(float re, float im){
        return new Complex(re, im);
    }

    public static Complex valueOfPolar(float r, float theta){
        return new Complex((float)(r * Math.cos(theta)), (float)(r * Math.sin(theta)));
    }
}

注意:用静态工厂方法代替构造函数后,构造函数就成了private的了,当然如果你希望同时也提供公有的构造函数也是可以的。 

 

2)它与构造函数不同,它每次被调用时,不要求非得创建一个新的对象。

 也正是因为这个特性,才让我更加喜欢静态工厂方法。例如在全局唯一性对象中通过getInstance()方法提供对该对象的返回。

 

3)它与构造函数不同,它可以返回类型的子类型对象。

 这样可以强迫使用者通过接口来引用被返回的对象,而不是通过实现来引用。这是一个我要从本书中学写的其中一个非常重要的好习惯。在读到【第34条】时还会对此进行进一步的展开。

 

缺点:

1)类如果不含有公有或者受保护的构造函数,就不能被继承。

我倒是觉得这更与【第3条】有些类似,设计一个类时,设计者是否希望这个类可被子类化(继承)或实例化,完全可以通过是否提供公有或者受保护的构造函数和构造函数的内容来控制。

某种意义上这也限制了继承的滥用,而鼓励使用复合(见【第14条】

2)静态工厂方法和其他静态方法一样,一般要在API文档中作出特别的说明。在没有强烈的需要下,你还是应该使用规范的构造函数。

 

常见静态工厂方法:

用的最多的就是 getInstance()了,一般非值类的静态工厂方法都是这个,用在唯一实例化的Session性质的类,再合适不过了。

valueOf()是大多数值类所提供的,不太严格地讲,该方法返回的实力与它的参数具有同样的值。它是一个非常有效地类型转换方式。 如: String s = String.valueOf(3 * 4);  // s = "12"

 

总结:静态工厂方法和公有构造函数各有各的好处。选择哪一个首先要基于理解。在没有充分理由的情况下,还是最好使用公有构造函数,毕竟它是语言提供的规范。

也就是说,本条的结论并不是静态工厂方法优于公有构造函数!

 

注:本书的第二版,可能将构造函数翻译为构造器。

我对第一版中绝大部分专有名词的翻译还是比较满意的,而且译者每每此时都把原英文单词附上了

(我印象比较深的一个个人感觉比较别扭的翻译是第35条的reflect “映像机制”,我个人更习惯于“反射”这个称呼)

 

 

【Effective Java 学习笔记】系列连载专题请见:
http://tonylian.iteye.com/categories/64208

 

4
1
分享到:
评论

相关推荐

    Java学习总结(2023/03/19)

    17. 使用私有静态工厂方法代替构造函数。 18. 优先考虑使用私有构造函数和公有工厂方法。 19. 使用私有构造函数实现不可实例化的工具类。 20. 使用枚举来实现Singleton模式。 21. 避免创建不必要的对象。 22. 使用...

    现代编程语言- Kotlin 之美 - 当下最火的编程语言欣赏.pdf

    #### EJ 第1条:考虑使用静态工厂方法代替构造器 在实例化对象的过程中,静态工厂方法相较于构造器具有明显的优势。这些优势不仅限于易于理解和避免不必要的对象创建,还包括能够灵活地返回原类型的任何子类型。...

    jdk-11.0.8_windows-x64_bin.rar

    4. **静态工厂方法代替构造函数( sealed classes)**:增强了类的封装性,控制了子类的扩展。 5. **文本块(Text Blocks)**:在Java 13引入,11中没有,但在后续版本中,这是一个显著提升代码可读性的特性,特别是...

    【05-面向对象(下)】

    基本数据类型的包装类 •八大数据类型的包装类分别为:Byte、Short、Integer、Long、Character、 Float、Double、Boolean。...函数式接口中被实现方法的第一个参数作为调用者,后面的参数全部传给该...

    Sun.310-035.Exam

    - **静态工厂方法**:静态工厂方法是一种常见的设计模式,用于代替构造函数创建对象。在本例中,`Alpha1.get`方法根据输入选择返回`Elephant`或`Lion`对象,这两个类都实现了`Animal`接口。 在提供的代码片段中,...

    创建型设计模式(下)

    - **懒汉式**:在第一次使用时才初始化,因此类加载速度快,但获取对象时可能会因为多线程同步问题而变慢。 在实际开发中,可以根据应用的需求和性能考虑来选择合适的单例模式实现方式。 #### 原型设计模式 原型...

    more effective C++

    - **实现**:通过私有构造函数、静态成员函数等手段限制对象的创建。 ##### 7.3 Item 27:要求或禁止在堆中产生对象 - **堆对象**:动态分配的对象。 - **实现**:通过使用智能指针等工具来管理堆对象的生命周期。 ...

    Java性能优化技巧集锦

    1. **避免使用`new`关键字创建对象**: 在创建类实例时,`new`关键字会触发构造函数链的调用,这可能会带来额外的开销。如果对象实现了`Cloneable`接口,可以使用`clone()`方法来创建副本,避免构造函数的调用。在...

    effecctivejava 第三版中文

    1. **构造器与工厂方法**:书中强调,类的构造器应该简洁且易于理解,同时推荐使用工厂方法来替代公开构造器,以提供更灵活的实例创建策略。 2. **枚举代替常量类**:枚举类型不仅提供了安全性和便利性,还能避免...

    effective c++ 第三版本有目录pdf

    1. **对象构造与析构**:书中强调了构造函数的重要性,如智能指针的使用,以及如何正确实现拷贝构造函数和赋值运算符来防止浅复制。同时,还介绍了构造函数初始化列表的使用,以确保对象的正确初始化。 2. **资源...

    设计模式第三部分.zip

    单例模式的关键在于防止其他对象创建额外的实例,通常通过私有构造函数和静态工厂方法实现。 2. **工厂模式**:工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,当客户端请求创建一...

    Symbian OS C++高效编程

    OS的异常 102.1 异常退出函数 102.2 使用new(ELeave)进行基于堆的内存分配 122.3 构造函数与析构函数 132.4 使用异常退出函数 142.5 用TRAP和TRAPD捕获异常退出 152.6 LeaveScan 202.7 小结 21第3章...

    二十三种设计模式【PDF版】

    《Thingking in Java》(第一版中文)是这样描述设计模式的:他在由 Gamma, Helm 和 Johnson Vlissides 简称 Gang of Four(四人 帮),缩写 GoF 编著的《Design Patterns》一书中被定义成一个“里程碑”。事实上,那本书...

    Effective及Exceptional系列

    - 知识点一:对象构造与析构,书中强调了初始化的重要性,推荐使用构造函数而非赋值操作来设置对象状态。 - 知识点二:智能指针的使用,提倡使用std::unique_ptr、std::shared_ptr等智能指针代替原始指针,以自动...

    EffectiveJava:有效的 Java 示例

    - **建造者模式**:推荐使用建造者模式来构造复杂对象,避免长参数列表和可变构造函数。 2. **接口与抽象类** - **接口优先于抽象类**:书中强调在设计API时应优先考虑使用接口,因为接口提供更好的多态性和可...

    亮剑.NET深入体验与实战精要2

    本书既考虑到实际开发中经常遇到的困惑和难题,也分析了解决问题的思路和方法,更总结出项目开发中不可或缺的技术点及思想。读者可以在欣赏一个个有趣例子的过程中,不知不觉具备开发真正商业项目的能力。 本书集...

    亮剑.NET深入体验与实战精要3

    本书既考虑到实际开发中经常遇到的困惑和难题,也分析了解决问题的思路和方法,更总结出项目开发中不可或缺的技术点及思想。读者可以在欣赏一个个有趣例子的过程中,不知不觉具备开发真正商业项目的能力。 本书集...

    一些前端面试题.pdf

    **浅拷贝**:只复制对象的第一层属性,对于对象内的对象或数组,只会引用原有地址。 **深拷贝**:完全复制对象及其所有的嵌套对象,生成一个全新的对象结构。 ### 前端路由的工作原理 前端路由使用JavaScript来...

Global site tag (gtag.js) - Google Analytics