Effictive java读书笔记一

Effictive java读书笔记

一、创建和销毁

1、考虑用静态工厂代替构造器
 

/**
* Returns a {@code Boolean} instance representing the specified
* {@code boolean} value. If the specified {@code boolean} value
* is {@code true}, this method returns {@code Boolean.TRUE};
* if it is {@code false}, this method returns {@code Boolean.FALSE}.
* If a new {@code Boolean} instance is not required, this method
* should generally be used in preference to the constructor
* {@link #Boolean(boolean)}, as this method is likely to yield
* significantly better space and time performance.
*
* @param b a boolean value.
* @return a {@code Boolean} instance representing {@code b}.
* @since 1.4
*/
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}

  • BigInteger(int ,int, random) 对比BigInteger.probablePrime ,静态方法有名称,易于阅读。
  • 静态工厂不会在每次调用时创建对象
Effictive java读书笔记一
  • 静态工厂可以返回原返回类型的任意子类,提高灵活性
api可以返回非公有的对象(隐藏实现类....基于接口的框架【interface-based-framework】;接口优于抽象类),在这种接口为静态工厂提供自然返回类型的模式中,接口不能有静态方法,接口Type的静态方法放在Types的不可实例化的类中(避免创建不必要的对象).参考Java Collections Framework集合的32个实现。
通过接口引用被返回的对象,而不是通过实现类来引用。
Effictive java读书笔记一




Effictive java读书笔记一

public interface Service {
//一些服务端特殊的方法
}

interface Provider{
Service newService();

}

class Services {
private Services() {
}

private static final Map<String, Provider> providers = new ConcurrentHashMap<String, Provider>();
public static final String DEFAULT_PROVIDER_NAME = "<def>";

/**
* 服务注册api
*
* @param p
*/
public static void registerProvider(Provider p) {
registerProvider(DEFAULT_PROVIDER_NAME, p);
}

public static void registerProvider(String name, Provider p) {
providers.put(name, p);
}

/**
* 服务入口api
* @return
*/
public static Service newInstance() {
return newInstance(DEFAULT_PROVIDER_NAME);
}

public static Service newInstance(String name){
Provider provider = providers.get(DEFAULT_PROVIDER_NAME);
if(null == provider )
throw new IllegalArgumentException("没有注册的此%d服务:" + name);

return provider.newService();
}

}
缺点:
静态工厂类如果不含有公有和受保护的构造方法就不能被子类化。
静态工厂和静态方法没什么区别。

2、多个构造器参数时考虑使用构建器
JavaBean模式的构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态(对象会产生不一致的状态。当你想要传入5个参数的时候,你必需将所有的setXX方法调用完成之后才行。然而一部分的调用者看到了这个对象后,以为这个对象已经创建完毕,就直接使用了,其实对象并没有完成创建)。无法仅仅通过检验构造器参数的有效性来保证一致性。试图使用这种对象,将会导致失败,类似于程序中包含了错误的代码,调试起来非常困难。与此相关的另一个不足在于,JavaBean模式阻止了把对象做成不可变的可能,这需要编码者付出额外的努力去确保它的线程安全。
Builder模式:不直接生成对象,而是让客户端在builder对象上调用类似setter的方法,来设置每个相关的可选参数。最后,客户端调用无参的build的方法来生成不可变的对象。这个builder是它构建的类的静态成员类。(Builder的内部类构造方法中只接收必传的参数,并且该必传的参数适用了final修饰符

public class LoveBuilder{
private final int poolSize;
private final int poolTimeLong;
private final String love;
private final String likeTo;
/**
* 静态内部成员类
*/
public static class Builder implements CommonBuilder<LoveBuilder>{
private final int poolSize;
private final int poolTimeLong;

private String love = "jack";
private String likeTo = "lily";

public Builder(int poolSize, int poolTimeLong) {
this.poolSize = poolSize;
this.poolTimeLong = poolTimeLong;
}

public Builder forLove(String val){
love = val;
return this;
}

public Builder likeTo(String val) {
likeTo = val;
return this;
}

public LoveBuilder builder() {
LoveBuilder loveBuilder = new LoveBuilder(this);
if(loveBuilder.love.length()<3){
throw new IllegalStateException("love的长度不足3:"+loveBuilder.love); // 线程安全
}
return loveBuilder;
}
}

public LoveBuilder(Builder builder) {
this.poolSize = builder.poolSize;
this.poolTimeLong = builder.poolTimeLong;
this.love = builder.love;
this.likeTo = builder.likeTo;
}

@Override
public String toString() {
return "[ " + "likeTo=" + this.likeTo + ",love=" + this.love + ",poolSize=" + this.poolSize + ",poolTimeLong=" + this.poolTimeLong + " ]";
}


public static void main(String[] args) {
LoveBuilder loveBuilder = new LoveBuilder.Builder(240, 80)
.forLove("周立波").likeTo("金星").builder();
System.out.print(loveBuilder);
}
}


这个对象不可变。builder模式模拟了具名的可选参数。
关于Builder的一点说明
线程安全问题
由于Builder是非线程安全的,所以如果要在Builder内部类中检查一个参数的合法性,必需要在对象创建完成之后再检查。

public LoveBuilder builder() {
LoveBuilder loveBuilder = new LoveBuilder(this);
if(loveBuilder.love.length()<3){
throw new IllegalStateException("love的长度不足3:"+loveBuilder.love); // 线程安全
}
return loveBuilder;
}


public LoveBuilder builder() {

if(love.length()<3){
throw new IllegalStateException("love的长度不足3:"+love); // 非线程安全
}
return new LoveBuilder(this);
}

经典的Builder模式
上面介绍的Builder模式当然不是“原生态”的啦,经典的Builder模式的类图如下:
Effictive java读书笔记一
builder
其中:
  • Product 产品抽象类。
  • Builder 抽象的Builder类。
  • ConcretBuilder 具体的Builder类。
  • Director 同一组装过程。
当然,之前实例中的Builder模式,是省略掉了Director的,这样结构更加简单。所以在很多框架源码中,涉及到Builder模式时,大多都不是经典GOF的Builder模式,而是省略后的。



Buider模式可以利用单个builder构建多个对象。builder的参数可以在创建对象期间进行调整,也可以随不同的对象改变。builder可以自动填充某些域,例如每次创建对象的时候自动增加***。