Effective Java笔记第一章创建和销毁对象第一节考虑用静态工厂方法代替构造器

Effective Java笔记第一章创建和销毁对象

引言
1.java语言支持四种类型:接口(interface),类(class),数组(array)和基本类型(primitive)。
2.接口(interface),类(class),数组(array)被称为引用类型,类实例和数组是对象。
3.类的成员由他的域(field),方法(method),成员类(member class)和成员接口(member interface)组成。
4.方法的签名(signature)由它的名称和所有参数类型组成,不包括返回类型。
5.术语中的API是指类,接口,构造器(constructor),成员和序列化形式(serialized form)。
6.接口中不能有静态方法。

第一节:考虑用静态工厂方法代替构造器
1.类可以通过静态工厂方法来提供他的客户端,而不是通过构造器。

2.静态工厂方法和构造器相比的四大优势
1)静态工厂方法有名称,当一个类需要多个带相同签名的构造器时,就用静态工厂方法代替构造器,并慎重选择名称以便区分。
2)静态工厂方法不必每次调用他们的时候都创建一个新的对象,使不可变类可以使用预先构建好的实例,或者将构建好的实例缓存,避免创建不必要的重复对象,可以为重复的调用返回相同对象。
3)静态工厂方法可以返回原返回类型的任何子类型的对象,具有灵活性。使得API可以返回对象同时又不会使对象的类变为公有,适用于基于接口的框架。可以要求客户端通过接口来引用被返回的对象,而不是通过它的实现类,这是个好习惯。
4)静态工厂方法在创建参数化类型实例的时候,使代码变得更简洁。在调用参数化类的构造器时,通常要求两次提供类型参数。
举个例子

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

假设HashMap中有以下这个静态工厂

public static <K,V> HashMap<K,V> newInstance(){
	return new HashMap<K,V>();
}

我们就可以用以下简介的代码代替

Map<String,List<String>> map=HashMap.newInstance();

3.服务提供者框架
服务提供者框架中有三个重要组件:服务接口(Service Interface),这是提供者实现的;提供者注册API(Provider Registration API),这是系统用来注册实现的,让客户端访问他们的;服务访问API(Service Access API),是客户端用来获取服务的实例的;第四个组件是可选的:服务提供者接口(Service Provider Interface),这些提供者负责其服务实现的实例,如果没有服务提供者接口,就按照类名称注册,并通过反射方式进行实例化。

简单实例

//Service Interface  服务接口
public interface Service {
     String demo();
}
//Service Provider Interface 服务提供者接口
public interface Provider {
    Service newServcie() ;
}
public class Services {
    //防止实例化
    private Services(){};
    //全局变量
    private static final Map<String,Provider> providers=new ConcurrentHashMap<String, Provider>();
    public static final String DEFAULT_PROVIDER_NAME="<def>";
    //Provider Registration API 提供者注册API
    public static void registerDefaultProvider(Provider p){
        registerProvider(DEFAULT_PROVIDER_NAME,p);
    }
    public static void registerProvider(String name,Provider p){
        providers.put(name,p);
    }
    //Service access API 服务访问API是灵活的静态工厂,构成了服务提供者框架的基础。
    public static Service newInstance(){
        return newInstance(DEFAULT_PROVIDER_NAME);
    }
    public static Service newInstance(String name){
        Provider provider = providers.get(name);
        if(provider==null){
            throw new IllegalArgumentException("No provider registered with name " + name);
        }
        return provider.newServcie();
    }
}
//测试
public class Test {
    public static void main(String[] args) {
        Services.registerDefaultProvider(DEFAULT_PROVIDER);
        Service service1 = Services.newInstance();
        System.out.println(service1);
        Services.registerProvider("aa",DEFAULT_PROVIDER);
        Service aa = Services.newInstance("aa");
        System.out.println(aa);
    }
    private static Provider DEFAULT_PROVIDER = new Provider() {
        @Override
        public Service newServcie() {
          return new Service() {
              @Override
              public String demo() {
                  return "ccccc";
              }
          };
        }
    };
 }

4.静态工厂方法的两大缺点
1)类如果不含公有的或者受保护的构造器,就不能被子类化。
2)静态工厂方法和其他的静态方法实际上没有任何区别。

上一篇:SQL Server2014 远程连接报错。.系统找不到指定的文件。


下一篇:使用dubbo进行远程调用时,遇到xxx must implement java.io.Serializable报错,以及Provider里面需要传递的对象为什么需要实现序列化接口?