1. 一个类对外提供获取自身实例对象的方法:
- 提供公有构造器;
- 公有的静态工厂方法(一个返回当前类实例的静态方法,包括当不限于我们平时所写的单例);
2. 静态工厂方法的优势 :
a. 可以随意组合要初始化的属性,通过不同的命名,不仅可以避免构造器的限制(一个类只能有一个带有指定签名的构造器),而且可以做到顾名思义;
b. 可以不用在每次调用时都创建一个新的对象,可以使用预先构建好的对象,或将构建好的对象缓存起来,进行重复利用,适用于经常请求创建相同对象,并且创建对象的代价很高,如常见的单例模式写法就是对这一点的应用;实例受控的类:能为重复的调用返回相同的类,有助于类控制某个时刻哪些实例应该存在,功能如下:
1.确保它是一个Singleton或者是不可实例化的;
2.使得不可变的类不会存在两个相等的实例,即当切仅当a==b时,才有a.equals(b)=true,如果保证了这一点, 就可以使用==代替equals,这样可以提高性能,枚举类型保证了这一点 ;
(==为hash地址相同,即同一个对象;equals为实例内容相同)
c. 可以返回原返回值类型的任何子类型的对象,有更好的灵活性,而且可以隐藏实现类(子类),使API更简洁,适用于基于接口的框架;
(如可以用工厂方法的不同命名标识不同的子类对象,也可以同一个工厂方法,通过参数(如Type)进行判断,返回不同类型的子类对象)
d. 创建参数化类型实例(即泛型)时,使代码更简洁,如:
3. 静态工厂方法的缺点
a. 类如果不含公有的(public)或受保护的(protected)构造器,就不能被子类化,不方便扩展和形成关系体系;
(不过某些情况也可以用组合代替继承,同样可以实现代码的复用)
(组合:即该类的实例做为新类的一个属性)
b. 与其他静态方法没有任何区别,不方便使用者查找使用;
(可以通过添加注释以及命名规范,弥补这个问题)
4. 实例演示:构造器与静态工厂方法
5. 之前有自学过iOS开发,静态工厂获取实例的方式,在Object-c中深有体现,只是他们叫做类工厂方法,就像下面代码这样:
二. 遇到多个构造器参数时要考虑使用构建器(建造者模式)如果有大量的可选参数需要任意组合,我们来想想看有哪些实现方案呢?
1. 使用构造器:不能任意的组合;
2. 使用公有静态工厂方法:需要提前写出足够多组合的工厂方法,而且参数过多时通过命名区分也将很不方便;
3. 使用JavaBeans:即无参构造 setter方法,但是这使得构造过程分到了多个调用中,而且不能有效的保证一致性,还有就是阻止了把类做成不可变的可能,需要额外保证它的线程安全性;
4. 使用Builder模式:
优点:既保证了安全性,又有很好的可读性,而且方便对参数添加约束条件,也可以自动填充某些参数而不提供给调用者去修改(即对客户端隐藏一些属性);
缺点:代码量增多,可能增加内存开销;
适用于参数比较多的情况,以上面所用对Person类为例;
通过建造者创建实例:
三. 用私有构造器或者枚举类型强化Singleton属性- 实例受控;
- 单例模式的饿汉式,懒汉式,都是需要将构造器私有化;
- 单元素的枚举类型已经成为实现 Singleton 的最佳方法;
四. 通过私有构造器强化不可实例化的能力有些类只有静态方法和静态属性,如一些工具类,比如自定义日志工具类LogUtil,我们不希望它可以创建实例,然而一个类在缺少构造器时,系统会默认提供一个公有无参的构造方法,这时我们可以显示的提供一个私有的构造方法,以保证该类不可实例化;
五. 避免创建不必要的对象例1:将字符串转为boolean类型的实现方法,使用Boolean.valueOf("true")要优于new Boolean("true"),其源码内部实现如下:
例2:还是以上面的Person类为例,现在新增加一个判断是否生育高峰期出生的方法;
注意这里是说避免创建不必要的对象,而不是尽量少的创建对象;
六. 消除过期的对象引用一般而言,只要类是自己管理内存,就应当注意内存泄漏问题;
例如:栈实现类ArrayStack,当栈先增长后收缩,栈内还维护着过期引用,这种情况称为无意识的对象保持,那么就需要在pop()方法中将已经出栈的元素设为空;
内存泄漏另一个常见来源是缓存,有下面几种解决方案:
1. 使用WeakHashMap代表缓存,缓存中的项过期后就会自动被删除;
2. 使用后台线程定时的清除没用的缓存,或者添加新的缓存时进行清除,使用LinkedHashMap.removeEldestEntry()就可以实现后一种方案;
3. 对于更加复杂的缓存,必须直接使用 java.lang.ref;
4. 监听器和其他回调:要取消注册或使用weak reference,如只将他们保存为WeakHashMap中的键;
七. 避免使用终结方法finalizer通常是不可预测的,也是很危险的,一般是不必要的,除非作为安全网,或者为了终止非关键的本地资源,若使用了终结方法,就要记住调用super.finalize,如果需要把终结方法与公有的非final类关联起来,请考虑使用终结方法守卫者,以确保即使子类的终结方法未能调用super.finalize, 该终结方法也会被执行;
我是今阳,如果想要进阶和了解更多的干货,欢迎关注公众号”今阳说“接收我的最新文章Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved