EffectiveJava——创建和销毁对象1

第1条:考虑使用静态工程方法代替构造器

一般情况下创建一个对象,我们都会直接调用其构造方法,但是还有另外一种方法——静态工厂方法(static factory method),例如下面方法:

public static Boolean valueOf(boolean b){
      return b?Boolean.TRUE:Boolean.FALSE;
}

既然标题说考虑使用静态工程方法代替构造器,那么它有什么好处呢?

静态工程方法与构造器不用的优势在于:

1,它们有名称

具有适当命名的静态工程方法更易使用,代码也更易阅读。
当一个类需要多个带有相同签名的构造器时,就使用静态工厂方法代替构造器,并慎重的选择名称以便突出他们之间的的区别

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

  • 如果需要经常创建相同的对象,并且创建对象的代价很高,可以考虑使用缓存对象,静态方法能够为重复的调用返回相同的对象(实例受控类)
  • 单利模式

总而言之,我们可以利用静态方法控制对象的创建

3,它们可以返回原始返回类型的任何子类型的对象

API可以返回对象,同时又不会是使对象的类变成共有的,以这种方式隐藏实现类会使API更加简洁,这项技术适用于基于接口的框架

公共的静态方法所返回的对象的类不仅可以是非共有的,而且该类还可以随着每次调用而发生变化,这取决于静态方法的参数值。从而提高了软件的可维护性和性能,返回的对象也可以随着软件的迭代升级而不同。

客户端用于不需要知道也不关心他们从静态方法得到的对象的类

比如我们值定义一个接口,而隐藏接口的实现类,在客户端调用我们的静态工厂方法时,我们根据参数返回各种实现的实例对象,从而隐藏了细节,在以后的软件升级中,我们甚至可以删除某些实现类,而客户端永远都不知道。在Android就有许多这样的做法,比如说Window,以及各种系统服务等。

这种灵活的方法构成了访服务提供者框架(service provider framework)的基础,如JDBC
服务提供者框架有三个重要的组件:
- 服务接口(service interface),用来提供实现者的
- 提供者注册(provider registration api),系统用来注册实现,供客户端访问的
- 服务方法API(service access api),供客户端获取服务实例

比如下面示例:
public interface Service {
//在服务接口里面可以定义一些方法
void send(String msg);
}

    /**服务提供接口*/
    public interface Provider{

        Service newService();
    }


/**不可实例化的class,提供服务端注册与访问*/
public class Services {
    private Services(){};
    /**存储所有服务*/
    private static final Map<String , Provider> mProviders = new ConcurrentHashMap<String, Service.Provider>();

    public static final String DEFAULT_PROVIDER_NAME = "def";
    /**提供注册api*/
    public static void registerDefaultProvider(Provider p){
        registerProvider(DEFAULT_PROVIDER_NAME , p);
    }

    private static void registerProvider(String defaultProviderName, Provider p) {
        mProviders.put(defaultProviderName, p);
    }

    /**service access api*/
    public static Service newInstance(){
        return newInstance(DEFAULT_PROVIDER_NAME);
    }

    private static Service newInstance(String defaultProviderName) {
        Provider p = mProviders.get(defaultProviderName);
        if(p == null){
            throw new IllegalArgumentException("no provider registered with name"+defaultProviderName);
        }
        return p.newService();
    }
}

服务端registerDefaultProvider注册服务提供者,客户端调用service access api——newInstance获取服务提供者,进而或许服务对象,而Service的实现细节由服务端实现。

4,在创建参数话类型的时候,它是代码变得更加简洁

当然在jdk1.7这已经不是问题了:

//1.6
Map<String,String> map = new HashMap<String,String>();
//static method
public static <K,V> Map<K,V> newInstance(){
   return new HashMap<K,V>
}

//1.7
Map<String,String> map = new HashMap<>();

当然静态方法也有其缺点:

静态工厂方法的缺点

1,如果类不含有公共的受保护的构造器,他们就不能被子类化。

解决:考虑使用复合(composition),而不是继承

2,静态工厂方法看起来与其他静态方法实际上没有任何区别。

静态工厂方法一般有如下命名:
- valueOf
- of
- newInstance
- getType
- newType

总结:静态过程方法和构造器各有用处,了解它们的长处,但是静态方法通常更加适合,因此切记第一反应就是提供构公共的构造方法而不是考虑使用静态工厂方法

你可能感兴趣的:(EffectiveJava——创建和销毁对象1)