Effective Java读书笔记1

一. 考虑用静态工厂方法代替构造方法

1. 什么是静态工厂方法

注意与设计模式中的工厂模式是不同的,它是用通过专门定义一个类来负责创建其他类的实例,其实例通常拥有共同的父类,其实现主要是靠Java的反射机制。

2. 静态工厂方法的优点

1.有名称

对于一个对象的实例化来说,如果使用构造方法的话,可以使用构造函数的重载来实现不同情况下的实例化,但是由于构造函数的名称都是类名,只是参数不同,导致可能会错误的调用某些构造函数。
对于静态工厂方法而言,就可以更改方法的名称,对于不同情况的实例化,就可以用不同的静态工厂方法。

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

使用构造函数时,每次实例化都会创建一个新的对象。
但是使用静态工厂方法时,,可以使用构建好的实例或者将构建好的实例缓存起来重复利用。

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

主要是利用Java的多态的特性,使工厂可以产生基类的同时加入子类的方法
例:

package com.company;
public class Practice{
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        Aniaml a = AnimalFactory.newInstance("Dog");
        a.getinfo();
    }
}
interface Aniaml{
    public void getinfo();
}
class Dog implements Aniaml{
    @Override
    public void getinfo() {
        System.out.println("I am a dog");
    }
}
class Fish implements Aniaml{
    @Override
    public void getinfo() {
        System.out.println("I am a fish");
    }
}
class AnimalFactory{
    public static Aniaml newInstance(String type) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Aniaml aniaml = null;
        aniaml = (Aniaml)Class.forName("com.company."+type).newInstance();
        return aniaml;
    }
}

运行结果:

I am a dog

通过上面的例子可以看出,使用这种方法就可以得到其他子类的信息。

4.使得代码更加简洁

在原书中,说道在调用参数化类型的构造器时,必须要指明类型参数,例如

 Map<String,List<String>> m = new HashMap<String,List<String>>();

但是现在,随着Java版本的更新,现在已经不需要指明类型参数了:以下也是可以的。

 Map<String,List<String>> m = new HashMap<>();

3. 静态工厂方法的缺点

1.类如果不包含共有的或者受保护的构造器,就不能被子类化
2.和静态方法实际上没有任何区别。其无法在API文档中明确标出。

二. 遇到多个构造器参数是要考虑用构建器

静态工厂方法和构造器都不能很好的扩展有大量可选参数。
比如有一个类表示包装食品外的营养成分表,其中:每份的含量,每份的卡路里是必选的,但是有超过20个歌可选域:总脂肪量,饱和脂肪量,转换脂肪量等等...
对于这样一个类,怎么编写呢?
1.使用重叠构造器:提供一个只有必选参数的构造器,第二个构造器有一个可选参数,第三个构造器有三个可选参数,以此类推。。。构造的时候就调用含有那些需要的可选参数的最小构造器即可。
但是随着参数的增加,new Fact(1,2,0,4,5,7)这样的结构就会变得越来越糟糕,参数过多就会导致很容易出错。
2.JavaBeans模式:即调用setter方法来设置每个需要的参数,这样的代码读起来也很容易。

facts.setServSize(1)
facts.setServing(2)
facts.setCal(4)
facts.setSodium(7)

但是这就阻止了把类做成不可变类的可能,类的属性很容易被修改。
3.Builder模式(构建器):先调用builder的有必要参数的构造器,在调用类似setter的方法来设置每个可选的参数,最后调用无参的build方法生成不可变的Fact对象

class Fact{
    private final int servingSize;//必选
    private final int servings;//必选
    private final int calories;//可选
    private final int sodium;//可选

    public static class Builder{
        private  int servingSize;//必选
        private  int servings;//必选

        private  int calories = 0;//可选
        private  int sodium = 0;//可选

        public Builder(int servingSize,int servings){
            this.servingSize = servingSize;
            this.servings = servings;
        }

        public Builder Calories(int val){
            calories = val; 
            return this;
        }

        public Builder Sodiun(int val){
            sodium = val;
            return this;
        }

        public Fact build(){
            return new Fact(this);
        }
    }

    private Fact(Builder builder){
        servingSize = builder.servingSize;
        servings = builder.servings;
        calories = builder.calories;
        sodium  = builder.sodium;
    }
}

构造时:

Fact fact = new Fact.Builder(200,3).Calories(34).Sodiun(67).build();

简而言之:如果类的构造器或者静态工厂方法中有很多参数,设计这种类时,Builder模式就是个不错的选择。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值