`
guitar427
  • 浏览: 4723 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

第1条--考虑用静态工厂方法代替构造器

阅读更多

    写在开头:走技术这条路永远也不能停止学习,工作快三年了,虽然一直都有坚持学东西,也经常在各大技术论坛闲逛,不过挺遗憾自己没有把学习的收获和心得记录下来,正好最近也不是很忙,就把之前的东西再重新理一遍,也正好做个记录。想了一下,还是从《Effective Java》开始吧,这本书我相信很多搞Java的人都看过,这算是我第二次从头看这本书吧,感觉在掌握了Java的基础并做了一些东西之后再来学习这本书真的是受益匪浅。
    下面是我认为这本书的几个最重要的作用:
    1.更深入地理解Java的核心特性。
    2.更高效地使用Java及其基本类库。
    3.培养良好的编码风格和编码习惯(正如作者所说本书关心如何编写出清晰、正确、可用、健壮、灵活和可维护的程序)。
    这本书是按照主题和条目来组织的,每一章是一个主题,每一个条目是作者的一个建议,如果你希望自己在技术的路上少走弯路、不断进步的话,可以说每一个建议都非常有用。
    我这里只是对作者的每条建议做一个学习的记录,不敢有太多自己的理解,用尽量少的语言概括描述一下,例子也大多会用原书中的例子。
    好了,终于介绍得差不多了,废话不多说了,进入正题:

  第1条--考虑用静态工厂方法代替构造器
既然要用静态工厂方法代替构造器,那首先得知道静态工厂方法是什么,有什么优势。
 这里说的静态工厂方法不是设计模式中的工厂模式,而是通过一个静态的方法返回类的实例,这个大家肯定都用过,单例就是一个例子。
下面是Boolean类型的示例:

public static Boolean valueof(boolean b){
  return b?Boolean.TRUE:Boolean.FALSE
}

 静态工厂方法与构造器不同的第一大优势在于,它们有名称。通过方法名可以较为准确地描述返回的对象实例。另外,构造器在参数相同的情况下只能通过参数顺序的不同来区分,这种构造器非常容易混淆,静态工厂方法可以有效地避免这种麻烦。

 

 静态工厂方法与构造器不同的第二大优势在于,不必在每次调用它们的时候都创建一个新对象。这个优势在某些情况下极为明显,还是拿Boolean类型来说明,Boolean.valueof(boolean)从不创建对象,Boolean.TRUE和Boolean.FALSE都是final的,它们只在初始化时创建一个实例,以后每次调用valueof方法都返回相同的实例。可以设想,如果每次都创建一个新的Bolean实例,在频繁使用的情况下将造成多大的内存浪费。


静态工厂方法与构造器不同的第三大优势在于,它们可以返回原返回类型的任何子类型的对象。用户只需要通过接口来引用被返回的对象,而不需要关注具体的实现类。这里原书中举了三个例子,这三个例子从不同的角度描述了这种方式的优势。
第一个是例子是java.util.Collections,在它的内部有很多Collection的非公有实现类(包括不可修改的集合、同步集合),这些实现类都通过静态工厂方法导出。这极大地减少了API的数量,用户不需要在一大堆的API文档前做选择了。
第二个例子是java.util.EnumSet,它根据底层枚举类型的大小来返回不同的实现类,这么做的好处是显而易见的,在它的后续版本中假如需要增加或者删除一些实现类对于它的使用者是没有任何影响的。
第三个例子就是服务提供者框架,最典型的应用就是JDBC。先来了解一下服务提供者框架的三个重要的组件:服务接口(Service Interface),这个是由提供者来实现的;提供者注册API(Provider Registration API),这是给服务提供者注册的接口;服务访问接口(Service Access API),是用户用来获取服务实例的。对于JDBC来说,Connection就是服务接口,DriverManager.registerDriver是提供者注册API,DriverManager.getConnection是服务访问API。这个框架的好处就是在编写时不需要先有服务提供者的具体实现。

 

静态工厂方法的第四大优势在于,在创建参数化类型实例的时候,它们使代码变得更加简洁。下面看一个对比:
方式1:Map<String,List<String>> m = new HashMap<String,List<String>>();
方式2:Map<String,List<String>> m = HashMap.newInstance();
你更喜欢哪种?毫无疑问是第2种方式,虽然这个例子的类型参数还不足够复杂。HashMap目前还没有提供这个静态工厂方法。

静态工厂方法的主要缺点在于,类如果不含公有的或受保护的构造器,就不能被子类化。它鼓励使用复合,而不是继承。如果你的类设计就是用来继承的,那就不能把构造器设置成私有的了。
静态工厂方法的第二个缺点在于,它们与其他的静态方法实际上没有任何区别。这个只是在API中不能明确地知道哪个是静态工厂方法,一般静态工厂方法都使用下面一些惯用的名称:valueof、of、getInstance、newInstance、getType、newType.

构造器和静态工厂方法各有利弊,在设计一个类的时候尽量优先考虑静态工厂。

分享到:
评论
3 楼 iamhere2012 2013-05-06  
实际上静态工厂的第一个缺点也就是它强制使用复合的的优点了。。。一日一记,终身受用
2 楼 stormhouse 2013-04-28  
8错,有空时也翻翻Effective Java
1 楼 wyfn18 2013-04-28  
写的真好

相关推荐

    Effective-Java读书笔记(上)

    ##### 用静态工厂方法代替构造器 在面向对象编程中,对象的创建通常是通过构造器来完成的。然而,在某些情况下,使用静态工厂方法来创建对象可能会更加灵活和高效。 **静态工厂方法的优势**: 1. **命名清晰**:...

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

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

    Effective Java第三版1

    1. **静态工厂方法**:相比构造器,静态工厂方法有优点如可以不返回新实例、允许返回同一实例(单例)、可以有更具选择性的访问控制,并且命名更自由。 2. **构建器(Builder pattern)**:当类有多个构造器参数时,...

    java effective 第二版中英文二份文件

    4. **使用静态工厂方法代替构造器**:静态工厂方法不需创建新类实例,可以返回之前创建的对象,实现单例模式或返回不可变对象。此外,它们无需在类声明时就确定,可以有更具表达力的名字。 5. **考虑用私有构造器或...

    【05-面向对象(下)】

    我们把该类的构造器使用Private修饰,从而把该 类的所有构造器隐藏起来。  –2.则需要提供一个public方法作为该类的访问点,用于创建该类的对象,且必须使用static修饰  –3.该类还必须缓存已经创建的对象,必须...

    javaCore_Logic

    - **方法**:阐述了如何设计高效的方法,包括避免过早优化,以及使用静态工厂方法代替构造器等。 2. **Java编程的逻辑.pdf** 这本书可能侧重于帮助开发者理解和掌握Java编程的基本逻辑和思维方法,包括: - **...

    effectice_java第二版 英文

    2. **条目2:考虑为静态工厂方法而不是构造器(Consider Static Factory Methods Instead of Constructors)** 静态工厂方法有命名灵活性,不需创建新类就能返回实例,还可以返回原类型的子类型,或者在不需要时...

    effecctivejava 第三版中文

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

    【JAVA 11】 Java SE Development Kit 11.0.16.1

    - 在某些集合类中,如`Optional`、`Map.of()`和`List.of()`,使用静态工厂方法代替传统的构造器,以提供不可变的集合实例,提高了代码的安全性。 5. **字符串串联优化**: - Java 11对字符串串联进行了优化,使用...

    Effective.Java3rd.zip

    9. **优先考虑静态工厂方法而非公共构造器**:静态工厂方法提供了更灵活的无状态类创建方式,例如,它们可以返回已存在的对象以节省资源。 10. **使用枚举代替常量类**:枚举不仅可以存储常量,还可以定义行为,比...

    jdk-11.0.8_windows-x64_bin.rar

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

    Effective-Java-2nd-Edition-(May-2008).zip_effective java

    6. **构造器与工厂方法**:讨论了构造器与工厂方法之间的权衡,指出工厂方法可以提供更好的灵活性,如延迟初始化和返回子类实例。 7. **接口与抽象类**:解释了接口和抽象类的选择依据,以及何时使用单例接口,何时...

    EFFECT JAVA 中文

    1. **构造器与工厂方法**:书中强调了如何正确使用构造器,包括私有构造器、工厂方法和静态工厂方法。静态工厂方法的优势在于它们可以有选择性地返回类的子类型实例,而无需暴露其实现细节。 2. **设计和实现equals...

    Java基础知识的详细总结

    - 使用`Constructor`和`Method`对象调用构造器和方法。 - 设置`Accessible`属性来访问私有成员。 #### 十、设计模式 设计模式是一套被反复使用的解决方案模板,用于解决软件设计中的常见问题。 - **常用的设计...

    Effective-java-3e-source-code:有效Java第三版的源代码,并进行了必要的补充以使其可运行

    再者,“尽可能使用静态工厂方法而非构造器”。静态工厂方法比构造器更加灵活,不改变类的实例化方式,且可以有更丰富的返回类型。源代码会展示如何定义和使用静态工厂方法,以及在哪些场景下它们更为适用。 “优先...

    Java性能优化技巧集锦

    - 当进行大量数据操作时,使用批处理更新或插入,而不是一条条执行,可以显著提高数据库操作性能。 13. **缓存策略** - 实施缓存策略,如使用 Ehcache 或 Redis,减少对后端服务的调用,提升响应速度。 14. **...

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

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

    创建型设计模式(下)

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

Global site tag (gtag.js) - Google Analytics