创建和销毁对象——用静态工厂方法代替构造器

Posted lbhym

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了创建和销毁对象——用静态工厂方法代替构造器相关的知识,希望对你有一定的参考价值。

参考资料:《Effective Java》,https://www.jianshu.com/p/ceb5ec8f1174

基础回顾

1.什么是构造器?

构造器与类同名,在新建一个类的对象时,构造器会运行,以便将实例初始化为所希望的状态。

每个类都会有一个默认的无参的构造器。也可以自己手动写一个构造器。

如,在People类中写一个构造器:

public People(String Name,int Age)
{
    this.Name=Name;
    this.Age=Age;    
}

然后新建一个关于这个类的实例

People a=new Prople("张三",18);

像上面这样,可以在new后面加入对应的参数。如果我们不加参数,就会调用默认的无参构造器。

 

2.工厂方法

这里的静态工厂方法并不是直接对应设计模式当中的工厂方法

静态工厂方法常用于类似LoaclDate或NumberFormat这种类当中。比如LocalDate.now等。

为什么会用静态工厂方法呢?比如NumberFormat.getCurrencyInstance()和NumberFormat.getPercentInstance()这两个工厂方法,一个得到的是货币类型的,一个是百分比类型的。

但是他们的接收参数都是一样的,构造器又必须得和类同名,如果非得用构造器去实现这个功能,还得添加其他参数,同时没有明确的名字去区分,增加了开发者的使用难度。

下面将会详细说出静态工厂方法的其他优势。

 

静态工厂方法的优势

先自己写个静态工厂方法

public class EJ01_01 {
    private int Num = 0;

    //静态工厂方法
    public static EJ01_01 convert(double Num) {
        EJ01_01 ej01_01 = new EJ01_01();
        ej01_01.Num = (int) Num;
        return ej01_01;
    }
    //测试可以返回子类
    public static EJ01_01_Son convert() {
        return new EJ01_01_Son();
    }

    public int Show() {
        return this.Num;
    }

    public int Add_10() {
        return this.Num + 10;
    }
}

class Test {
    public static void main(String args[]) {
        EJ01_01 test = EJ01_01.convert(1.2);
        System.out.println(test.Add_10());//输出11
        System.out.println(test.Show());//输出1
    }
}
//子类
class EJ01_01_Son extends EJ01_01 {
}

 

1.静态工厂方法有名称。

这个不用多说,就像上面的NumberFormat.getCurrencyInstance()和NumberFormat.getPercentInstance()一样。开发者一眼就可以看出他们的区别。

2.不必在每次调用时都创建一个新的对象。

如上面的代码。在测试类中:

EJ01_01 test = EJ01_01.convert(1.2);

并没有新建任何对象,直接调用。

3.它可以返回原返回类型的任何子类

构造函数只能返回自己原本的类型,但是在静态工厂方法中是可以返回子类的。如:

 //测试可以返回子类
    public static EJ01_01_Son convert() {
        return new EJ01_01_Son();
    }

我测试了也可以返回其他常见的数据类型,比如convert方法的返回类型可以直接写成int,但是不见资料当中有任何提及,也不知道这种写法是否规范。

4.可以减少对外暴露的属性

下面代码的功能,调用Get_Type时,只能输入规定的参数,然后输出对应的数据。

这种情况非常常见,比如一些方法只让输入MAX、MIN这种参数,输入其他参数直接报错。

但是我们如果只用构造器来实现,是限制不了用户输入的是什么。下面的代码相当于把静态工厂方法当成构造函数的参数,用户只能调用对应的静态工厂方法,然后工厂方法进行赋值。

class Get_Type {
    public static final int TYPE_Small = 1;
    public static final int TYPE_Moderate = 2;
    public static final int TYPE_Big = 3;

    private Get_Type(int type) {
        switch (type){
            case 1:
                System.out.println("这是小号");
                break;
            case 2:
                System.out.println("这是中号");
                break;
            case 3:
                System.out.println("这是大号");
                break;
        }
    }

    public static Get_Type Small() {
        return new Get_Type(TYPE_Small);
    }
    public static Get_Type Moderate() {
        return new Get_Type(TYPE_Moderate);
    }
    public static Get_Type Big() {
        return new Get_Type(TYPE_Big);
    }
}

//调用
class Test2{
    public static void main(String args[]){
        Get_Type get_small=Get_Type.Big();//输出这是大号
    }
}

 静态工厂方法不止这几点,其他的一些优势我可能还没发现,剩下知道的几个以目前的能力来看,还无法完全理解。

以上是关于创建和销毁对象——用静态工厂方法代替构造器的主要内容,如果未能解决你的问题,请参考以下文章

Effective Java 学习笔记之创建和销毁对象

Effective Java 读书笔记之一 创建和销毁对象

EffectiveJava——第二章 创建和销毁对象

创建和销毁对象

Effictive Java学习笔记1:创建和销毁对象

Effective Java阅读笔记——创建和销毁对象