优点:
常见的静态工厂方法名:
当一个类没有提供静态工厂方法的时候,我们才需要使用工厂模式。
缺点:
静态工厂和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数。两种常见方案:
重叠构造器模式可行,但是当有很多参数的时候,客户端代码会很难编写,并且仍然较难以阅读。
JavaBeans模式在构造过程中可能处于不一致的状态,且阻止了把类做成不可变的可能。
第三种就是构建者模式(Builder模式):不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个builder对象。然后客户端在builder对象上调用类似setter的方法,来设置每个相关的可选参数。最后客户端调用无参的build方法来生成不可变的对象。这个builder是它构建的类的静态成员类。
不足:为了创建对象,必须先创建它的构建器;Builder模式还比重叠构造器模式更加冗长,因为它只在有很多参数的时候才使用。
如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是中不错的选择,特别是当大多数参数都是可选的时候。
传统单例实现存在的一个问题是一旦实现了序列化接口,那么它们不再保持单例了,因为readObject()方法一直返回一个新的对象就像java的构造方法一样,可以通过使用readResolve()方法来避免:
//readResolve to prevent another instance of Singleton private Object readResolve(){ return INSTANCE; }
一个使用枚举类型来实现的单例模式:
// 需要应用单例模式的资源,具体可以表现为网络连接,数据库连接,线程池等 class Resource{ } public enum SomeThing { INSTANCE; private Resource instance; private SomeThing() { instance = new Resource(); } public Resource getInstance() { return instance; } }
获取资源的方式很简单,只要SomeThing.INSTANCE.getInstance()即可获得所要实例。因为在枚举中明确了构造方法为私有,在我们访问枚举实例时会执行构造方法,同时,每个枚举实例都是static final类型的,也就表明只能被实例化一次。
工具类(utility class)不希望被实例化,实例没有任何意义。在缺少显式构造器的时候,编译器会自动提供一个公有的、无参的缺省构造器。所以我们只要让这个类包含私有构造器,它就不能被实例化了。当然副作用就是,这个类就不能被子类化了。所有的构造器都必须显式或隐式地调用超类构造器,在这种情形下,子类就没有可访问的超类构造器课调用了。
对于同时提供了静态工厂方法和构造器的不可变类,通常可以使用静态工厂方法而不是构造器,以避免创建不必要的对象。
除了重用不可变的对象之外,也可以重用哪些已知不会被修改的可变对象。
当你应该重用现有对象的时候,请不要创建新的对象。
过期引用是指永远也不会再被解除的引用。如果一个对象引用被无意识地保留起来了,那么,垃圾回收机制不仅不会处理这个对象,而且也不会处理被这个对象所引用的所有其他对象。即使只有少量的几个对象引用被无意识地保留下来,也会有许许多多的对象被排除在垃圾回收机制之外,从而对性能造成潜在的重大影响。
这类问题的修复方法是:一旦对象引用已经过期,只需清空这些引用即可。
清空过期引用的另一个好处是:如果它们以后又被错误的解除引用,程序就会立即抛出NullPointerException异常,而不是悄悄地错误运行下去。
清空对象引用应该是一种例外,而不是一种规范行为。消除过期引用最好的方法是让包含该引用的变量结束其生命周期。
除了过期引用,内存泄漏的另一个常见来源是缓存。可能的解决方案:
内存泄漏的第三个常见来源是监听器和其他回调。如果实现了一个API,客户端在这个API中注册回调,却没有显式地取消注册,那么除非你才去某些动作,否则它们就会积聚。确保回调立即被当作垃圾回收的最佳方法是只保存它们的弱引用。
终结方法的缺点在于不能保证会被及时地执行。从一个对象变得不可到达开始,到它的终结方法被执行,所花费的这段时间是任意长的。Java语言规范不仅不保证终结方法会被及时地执行,而且根本就不保证它们会被执行。所以,不应该依赖终结方法来更新重要的持久状态。
如果类的对象中封装的资源(例如文件或者线程)确实需要终止,应该提供一个显式的终止方法,并要求该类的客户端在每个实例不再有用的时候调用这个方法。显式终止方法的典型例子InputStream、OutputStream和java.sql.Connection上的close方法。显式的终止方法通常与try-finally结构结合起来使用,以确保及时终止。