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 ,静态方法有名称,易于阅读。
  • 静态工厂不会在每次调用时创建对象

  • 静态工厂可以返回原返回类型的任意子类,提高灵活性

api可以返回非公有的对象(隐藏实现类....基于接口的框架【interface-based-framework】;接口优于抽象类),在这种接口为静态工厂提供自然返回类型的模式中,接口不能有静态方法,接口Type的静态方法放在Types的不可实例化的类中(避免创建不必要的对象).参考Java Collections Framework集合的32个实现。

通过接口引用被返回的对象,而不是通过实现类来引用。

 


 

 

 

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模式的类图如下:

builder

其中:

  • Product 产品抽象类。
  • Builder 抽象的Builder类。
  • ConcretBuilder 具体的Builder类。
  • Director 同一组装过程。

当然,之前实例中的Builder模式,是省略掉了Director的,这样结构更加简单。所以在很多框架源码中,涉及到Builder模式时,大多都不是经典GOF的Builder模式,而是省略后的。


 

 

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

posted @ 2018-02-26 13:46  MysticalYcc  阅读(13)  评论(0)    收藏  举报