创建和销毁对象
一.静态工厂方法代替构造器
静态工厂方法的优缺点
优点:
1.可以自定义名称(可以将功能表述的更加清晰)
2.不必每次调用都创建新的对象(同一对象重复使用)
3.返回的类型可以是原返回类型的任何子类型对象
4.简化创建对象时的代码
缺点:
1.如果不含有公开的构造器,就不能被子类化
2.和普通的静态方法没有区别
二.遇到多个构造器参数时考虑用构建器
如果我们现在需要编写一个描述客户信息的类,在客户的信息中名字是一定有的,其他的信息都是可能用,我们使用三种方法去完成:
1.重叠构造器方法(代码已经简化)
1 /**
2 * 客户信息
3 */
4 public class Customer {
5 private String name;//姓名
6 private String profession;//职业
7 private int age;//年龄
8 private String gender;//性别
9
10 public Customer(String name){
11 this.name=name;
12 }
13
14 public Customer(String name,String profession){
15 this.name=name;
16 this.profession=profession;
17 }
18
19 public Customer(String name,String profession,int age){
20 this.name=name;
21 this.profession=profession;
22 this.age=age;
23 }
24
25 public Customer(String name,String profession,int age,String gender){
26 this.name=name;
27 this.profession=profession;
28 this.age=age;
29 this.gender=gender;
30 }
31 }
创建实例:
Customer customer=new Customer("李雷", "程序员", 27, "男");
总结:这里是简化后的代码,此实例才4个参数就如此繁琐,随着参数的增加,将会失去控制。
2.JavaBean模式(调用无参构造方法,然后用set方法赋值)
1 /**
2 * 客户信息
3 */
4 public class customer {
5 private String name;//姓名
6 private String profession;//职业
7 private int age;//年龄
8 private String gender;//性别
9
10 public customer(){}
11
12 public void setName(String name) {
13 this.name = name;
14 }
15
16 public void setProfession(String profession) {
17 this.profession = profession;
18 }
19
20 public void setAge(int age) {
21 this.age = age;
22 }
23
24 public void setGender(String gender) {
25 this.gender = gender;
26 }
27 }
创建实例:
customer customer=new customer();
customer.setAge(27);
customer.setGender("男");
customer.setName("李雷");
customer.setProfession("程序员");
总结:创建实例容易,也比较容易阅读,但是由于对象的构造过程被分到了几部调用中,JavaBean可能处于不一致的状态,而且使用此模式无法将类制作成不可变的。
3.构建器(Builder模式)
1 /**
2 * 客户信息
3 */
4 public class Customer {
5 private final String name;//姓名
6 private final String profession;//职业
7 private final int age;//年龄
8 private final String gender;//性别
9
10 public static class Builder{
11 private final String name;
12
13 private String profession="无";
14 private int age=0;
15 private String gender="未知";
16
17 public Builder(String name){
18 this.name=name;
19 }
20
21 public Builder profession(String val){
22 profession=val;
23 return this;
24 }
25
26 public Builder age(int val){
27 age=val;
28 return this;
29 }
30
31 public Builder gender(String val){
32 gender=val;
33 return this;
34 }
35
36 public Customer build(){
37 return new Customer(this);
38 }
39 }
40
41 private Customer(Builder builder){
42 name=builder.name;
43 profession=builder.profession;
44 age=builder.age;
45 gender=builder.gender;
46 }
47 }
创建实例:
创建对象时,类名后面加括号表示调用无参的构造函数;不加括号表示调用默认的构造函数或唯一的构造函数
Customer customer=new Customer.Builder("李雷").age(27).gender("男").profession("程序员").build();
总结:编写容易,易于阅读,而且模拟了具名的可选参数,安全性高,后期的扩展性强。
3.单元素枚举是实现Singleton的最佳方法
1 public enum Elvis {
2 INSTANCE;
3
4 public void leaveTheBuilding(){
5 System.out.println("Singleton!");
6 }
7 }
创建实例:
Elvis elvis=Elvis.INSTANCE;
4.消除对其对象的引用
下面是一个栈的简单实现:
public class Stack {
private Object[] elements;
private int size=0;
private static final int DEFAULE_INITAL_CAPACITY=16;
public Stack(){
elements=new Object[DEFAULE_INITAL_CAPACITY];
}
public void push(Object e){
ensureCapacity();
elements[size++]=e;
}
public Object pop(){
if (size==0) {
throw new EmptyStackException();
}
return elements[--size];
}
public void ensureCapacity(){
if (elements.length==size) {
elements=Arrays.copyOf(elements, 2*size+1);
}
}
}
如果一个栈显示增长,然后再收缩,那么从栈中弹出的对象将不会被当做垃圾回收,我们应该将过期的引用清空,将pop方法改动如下:
public Object pop(){
if (size==0) {
throw new EmptyStackException();
}
elements[size]=null;
return elements[--size];
}