文章目录
  1. 1. 引言
  2. 2. 思考
  3. 3. 静态工厂方法和构造器
  4. 4. 使用构建器
  5. 5. 单例属性的强化
  6. 6. 对象的销毁
  7. 7. 结束语

引言

本博客的内容完全是为记录自己的一些读书感悟,如果喜欢可以进行阅读如有问题请指正,谢谢。

思考

  1. 什么是构造器,什么是静态工厂方法?
  2. 什么时候用构造器,什么时候用静态工厂方法?

静态工厂方法和构造器

静态工厂方法的优点:

  1. 静态方法是有名称的,有具体的名称更易于使用者去阅读和了解其功能。如果我需要多个构造器时,使用静态工厂方法可能是最好的。多个构造器除了参数类型等区分不同的功能再没有其他的方式,极易用错。但是静态的构工厂方法可以为每一个提供不同的名称,很容易区分。这种情况使用静态工厂是个好的实现方式。
  2. 静态工厂方法了解加载机制的都知道,它不会再每一次调用时都构建一个新的对象,对于频繁调用时是一个不错的方式。
  3. 静态工厂方法有返回值,在某种用途上我们能够更好的实现。例如后面的构建器。
  4. 实例化参数类型时更加的简洁明了。
1
2
3
4
5
6
7
8
//实例化时
Map<String, List<String>> map = new HashMap<String, List<String>>();
//Google Guava提供的静态实例化方法
public static<K, V> HashMap<K, V> newHashMap(){
reutrn new HashMap<K, V>();
}
//实例化时
Map<String, List<String>> map = Maps.newHashMap();

静态工厂方法的缺点:

  1. 类如果没有构造器,就不能被子类去类化。
  2. 它们与其他的静态方法没什么区别。API文档中不会提供静态方法的说明,有时候你可能只看文档无法知道如何实例化一个类(当然看源码很容易就知道了)

使用构建器

  1. 使用构造器是解决静态工厂和构造器的局限性,它们不能很好的扩展到大量的可选择参数。
  2. 普通的要灵活的使用构造的参数个数可能要写大量的构造器去处理,相当的繁琐。
  3. 前期可能使用的参数较少感觉使用构建器反而更复杂,但是后期扩展时很方便。

构建器的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class Build {
private String name;
private Integer age;
private String desc;
public static class BuildForm {
private String name;
private Integer age;
private String desc;
public BuildForm() {
}
public BuildForm nameBuild(String name) {
this.name = name;
return this;
}
public BuildForm ageBuild(Integer age) {
this.age = age;
return this;
}
public BuildForm descBuild(String decs) {
this.desc = decs;
return this;
}
public Build buildData() {
return new Build(this);
}
}
//创建私有构造器防止调用默认构造器处理和处理内部赋值
private Build(BuildForm buildForm){
this.name = buildForm.name;
this.age = buildForm.age;
this.desc = buildForm.desc;
}
@Override
public String toString() {
return "Build{" +
"name='" + name + '\'' +
", age=" + age +
", desc='" + desc + '\'' +
'}';
}
}

构建器的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Main {
public static void main(String[] argv) {
Build buildOne = new Build.BuildForm()
.nameBuild("AA")
.buildData();
Build buildTwo = new Build.BuildForm()
.nameBuild("BB")
.ageBuild(12)
.buildData();
Build buildThree = new Build.BuildForm()
.nameBuild("CC")
.ageBuild(12)
.descBuild("啊哈哈")
.buildData();
System.out.println(buildOne.toString());
System.out.println(buildTwo.toString());
System.out.println(buildThree.toString());
}
}

测试结果如下:

1
2
3
Build{name='AA', age=null, desc='null'}
Build{name='BB', age=12, desc='null'}
Build{name='CC', age=12, desc='啊哈哈'}

以上就是一个简单的构建器,大家可以根据自己的需求去使用。

单例属性的强化

私有的构造器

就如同我上面代码中写到的,如果不使用私有的构造器去处理类,虽然我们的实现是单例的,但是使用者完全可以使用默认的构造器去创建出来新的对象,有时候就违背我们的初衷。

枚举的方式

我们可以使用枚举的方式去创建一个单例模式,这样就不会出现上述的情况。创建的方式如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//创建一个类
public class Factory {
}
//枚举的方式实例化类
public enum EnumFactory {
DATE;
private Factory factory;
public void buildSingleton(){
factory = new Factory();
}
public Factory getFactory(){
return factory;
}
}
//类的使用
public class Main {
public static void main(String[] argv) {
Factory factory = EnumFactory.DATE.getFactory();
}
}

三种单例的创建模式,枚举的方式可能是现在做好的方法。

对象的销毁

内存泄露

对象有创建必然存在销毁,java提供有自己的垃圾回收机制。但是并不代表java不会出现内存泄露。所以我们需要消除过期的对象引用,若过期的对象引用一直存在垃圾回收器就不会去回收资源。一般这种情况发生在引用缓存中。开发中要注意这类情况。下面是三种容易发生内存泄露的情况。

  1. 无意识的泄露,一般是代码考虑不周全导致,没有考虑泄露的意识。
  2. 缓存中存放的对象,一般需要去维护,不然容易出现泄露。
  3. 监听器和回调,这种情况一般是需要维护对象的长期有效的,但是使用完成如果不进行注销就会出现泄露。

避免使用终结方法

java有提供终结方法来让开发者去终结,但是终结方法的线程优先级极低,我们并不能去确定终结方法一定会执行,有不能确定终结方法执行的时间。当然有些情况是需要去使用终结方法的,例如流的关闭,一般要配合try….finally来使用。

结束语

一些简单的介绍,如果要很好的了解建议大家亲自去看看这本书。希望浅薄的理解能对你的开发有帮助。

文章目录
  1. 1. 引言
  2. 2. 思考
  3. 3. 静态工厂方法和构造器
  4. 4. 使用构建器
  5. 5. 单例属性的强化
  6. 6. 对象的销毁
  7. 7. 结束语